aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorTadeusz Struk <tadeusz.struk@intel.com>2015-02-06 13:25:20 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2015-02-28 05:31:35 -0500
commit81e397d937a8e9f46f024a9f876cf14d8e2b45a7 (patch)
treea1bd2c28113cf99ebc916e8ae76615ac11ffa356 /arch/x86
parentd2e3ae6f3abad839214f7b05c34075a1a7c82470 (diff)
crypto: aesni - make driver-gcm-aes-aesni helper a proper aead alg
Changed the __driver-gcm-aes-aesni to be a proper aead algorithm. This required a valid setkey and setauthsize functions to be added and also some changes to make sure that math context is not corrupted when the alg is used directly. Note that the __driver-gcm-aes-aesni should not be used directly by modules that can use it in interrupt context as we don't have a good fallback mechanism in this case. Signed-off-by: Adrian Hoban <adrian.hoban@intel.com> Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/crypto/aesni-intel_glue.c164
1 files changed, 110 insertions, 54 deletions
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index 947c6bf52c33..6893f4947583 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -890,15 +890,12 @@ out_free_ablkcipher:
890 return ret; 890 return ret;
891} 891}
892 892
893static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key, 893static int common_rfc4106_set_key(struct crypto_aead *aead, const u8 *key,
894 unsigned int key_len) 894 unsigned int key_len)
895{ 895{
896 int ret = 0; 896 int ret = 0;
897 struct crypto_tfm *tfm = crypto_aead_tfm(parent); 897 struct crypto_tfm *tfm = crypto_aead_tfm(aead);
898 struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(parent); 898 struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(aead);
899 struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
900 struct aesni_rfc4106_gcm_ctx *child_ctx =
901 aesni_rfc4106_gcm_ctx_get(cryptd_child);
902 u8 *new_key_align, *new_key_mem = NULL; 899 u8 *new_key_align, *new_key_mem = NULL;
903 900
904 if (key_len < 4) { 901 if (key_len < 4) {
@@ -943,20 +940,31 @@ static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key,
943 goto exit; 940 goto exit;
944 } 941 }
945 ret = rfc4106_set_hash_subkey(ctx->hash_subkey, key, key_len); 942 ret = rfc4106_set_hash_subkey(ctx->hash_subkey, key, key_len);
946 memcpy(child_ctx, ctx, sizeof(*ctx));
947exit: 943exit:
948 kfree(new_key_mem); 944 kfree(new_key_mem);
949 return ret; 945 return ret;
950} 946}
951 947
952/* This is the Integrity Check Value (aka the authentication tag length and can 948static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key,
953 * be 8, 12 or 16 bytes long. */ 949 unsigned int key_len)
954static int rfc4106_set_authsize(struct crypto_aead *parent,
955 unsigned int authsize)
956{ 950{
957 struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(parent); 951 struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(parent);
958 struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm); 952 struct crypto_aead *child = cryptd_aead_child(ctx->cryptd_tfm);
953 struct aesni_rfc4106_gcm_ctx *c_ctx = aesni_rfc4106_gcm_ctx_get(child);
954 struct cryptd_aead *cryptd_tfm = ctx->cryptd_tfm;
955 int ret;
959 956
957 ret = crypto_aead_setkey(child, key, key_len);
958 if (!ret) {
959 memcpy(ctx, c_ctx, sizeof(*ctx));
960 ctx->cryptd_tfm = cryptd_tfm;
961 }
962 return ret;
963}
964
965static int common_rfc4106_set_authsize(struct crypto_aead *aead,
966 unsigned int authsize)
967{
960 switch (authsize) { 968 switch (authsize) {
961 case 8: 969 case 8:
962 case 12: 970 case 12:
@@ -965,51 +973,23 @@ static int rfc4106_set_authsize(struct crypto_aead *parent,
965 default: 973 default:
966 return -EINVAL; 974 return -EINVAL;
967 } 975 }
968 crypto_aead_crt(parent)->authsize = authsize; 976 crypto_aead_crt(aead)->authsize = authsize;
969 crypto_aead_crt(cryptd_child)->authsize = authsize;
970 return 0; 977 return 0;
971} 978}
972 979
973static int rfc4106_encrypt(struct aead_request *req) 980/* This is the Integrity Check Value (aka the authentication tag length and can
974{ 981 * be 8, 12 or 16 bytes long. */
975 int ret; 982static int rfc4106_set_authsize(struct crypto_aead *parent,
976 struct crypto_aead *tfm = crypto_aead_reqtfm(req); 983 unsigned int authsize)
977 struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
978
979 if (!irq_fpu_usable()) {
980 struct aead_request *cryptd_req =
981 (struct aead_request *) aead_request_ctx(req);
982 memcpy(cryptd_req, req, sizeof(*req));
983 aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
984 return crypto_aead_encrypt(cryptd_req);
985 } else {
986 struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
987 kernel_fpu_begin();
988 ret = cryptd_child->base.crt_aead.encrypt(req);
989 kernel_fpu_end();
990 return ret;
991 }
992}
993
994static int rfc4106_decrypt(struct aead_request *req)
995{ 984{
985 struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(parent);
986 struct crypto_aead *child = cryptd_aead_child(ctx->cryptd_tfm);
996 int ret; 987 int ret;
997 struct crypto_aead *tfm = crypto_aead_reqtfm(req);
998 struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
999 988
1000 if (!irq_fpu_usable()) { 989 ret = crypto_aead_setauthsize(child, authsize);
1001 struct aead_request *cryptd_req = 990 if (!ret)
1002 (struct aead_request *) aead_request_ctx(req); 991 crypto_aead_crt(parent)->authsize = authsize;
1003 memcpy(cryptd_req, req, sizeof(*req)); 992 return ret;
1004 aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
1005 return crypto_aead_decrypt(cryptd_req);
1006 } else {
1007 struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
1008 kernel_fpu_begin();
1009 ret = cryptd_child->base.crt_aead.decrypt(req);
1010 kernel_fpu_end();
1011 return ret;
1012 }
1013} 993}
1014 994
1015static int __driver_rfc4106_encrypt(struct aead_request *req) 995static int __driver_rfc4106_encrypt(struct aead_request *req)
@@ -1185,6 +1165,78 @@ static int __driver_rfc4106_decrypt(struct aead_request *req)
1185 } 1165 }
1186 return retval; 1166 return retval;
1187} 1167}
1168
1169static int rfc4106_encrypt(struct aead_request *req)
1170{
1171 int ret;
1172 struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1173 struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
1174
1175 if (!irq_fpu_usable()) {
1176 struct aead_request *cryptd_req =
1177 (struct aead_request *) aead_request_ctx(req);
1178
1179 memcpy(cryptd_req, req, sizeof(*req));
1180 aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
1181 ret = crypto_aead_encrypt(cryptd_req);
1182 } else {
1183 kernel_fpu_begin();
1184 ret = __driver_rfc4106_encrypt(req);
1185 kernel_fpu_end();
1186 }
1187 return ret;
1188}
1189
1190static int rfc4106_decrypt(struct aead_request *req)
1191{
1192 int ret;
1193 struct crypto_aead *tfm = crypto_aead_reqtfm(req);
1194 struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
1195
1196 if (!irq_fpu_usable()) {
1197 struct aead_request *cryptd_req =
1198 (struct aead_request *) aead_request_ctx(req);
1199
1200 memcpy(cryptd_req, req, sizeof(*req));
1201 aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
1202 ret = crypto_aead_decrypt(cryptd_req);
1203 } else {
1204 kernel_fpu_begin();
1205 ret = __driver_rfc4106_decrypt(req);
1206 kernel_fpu_end();
1207 }
1208 return ret;
1209}
1210
1211static int helper_rfc4106_encrypt(struct aead_request *req)
1212{
1213 int ret;
1214
1215 if (unlikely(!irq_fpu_usable())) {
1216 WARN_ONCE(1, "__gcm-aes-aesni alg used in invalid context");
1217 ret = -EINVAL;
1218 } else {
1219 kernel_fpu_begin();
1220 ret = __driver_rfc4106_encrypt(req);
1221 kernel_fpu_end();
1222 }
1223 return ret;
1224}
1225
1226static int helper_rfc4106_decrypt(struct aead_request *req)
1227{
1228 int ret;
1229
1230 if (unlikely(!irq_fpu_usable())) {
1231 WARN_ONCE(1, "__gcm-aes-aesni alg used in invalid context");
1232 ret = -EINVAL;
1233 } else {
1234 kernel_fpu_begin();
1235 ret = __driver_rfc4106_decrypt(req);
1236 kernel_fpu_end();
1237 }
1238 return ret;
1239}
1188#endif 1240#endif
1189 1241
1190static struct crypto_alg aesni_algs[] = { { 1242static struct crypto_alg aesni_algs[] = { {
@@ -1366,8 +1418,12 @@ static struct crypto_alg aesni_algs[] = { {
1366 .cra_module = THIS_MODULE, 1418 .cra_module = THIS_MODULE,
1367 .cra_u = { 1419 .cra_u = {
1368 .aead = { 1420 .aead = {
1369 .encrypt = __driver_rfc4106_encrypt, 1421 .setkey = common_rfc4106_set_key,
1370 .decrypt = __driver_rfc4106_decrypt, 1422 .setauthsize = common_rfc4106_set_authsize,
1423 .encrypt = helper_rfc4106_encrypt,
1424 .decrypt = helper_rfc4106_decrypt,
1425 .ivsize = 8,
1426 .maxauthsize = 16,
1371 }, 1427 },
1372 }, 1428 },
1373}, { 1429}, {