diff options
author | Tadeusz Struk <tadeusz.struk@intel.com> | 2015-02-06 13:25:20 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2015-02-28 05:31:35 -0500 |
commit | 81e397d937a8e9f46f024a9f876cf14d8e2b45a7 (patch) | |
tree | a1bd2c28113cf99ebc916e8ae76615ac11ffa356 /arch/x86 | |
parent | d2e3ae6f3abad839214f7b05c34075a1a7c82470 (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.c | 164 |
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 | ||
893 | static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key, | 893 | static 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)); | ||
947 | exit: | 943 | exit: |
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 | 948 | static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key, |
953 | * be 8, 12 or 16 bytes long. */ | 949 | unsigned int key_len) |
954 | static 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 | |||
965 | static 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 | ||
973 | static 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; | 982 | static 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 | |||
994 | static 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 | ||
1015 | static int __driver_rfc4106_encrypt(struct aead_request *req) | 995 | static 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 | |||
1169 | static 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 | |||
1190 | static 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 | |||
1211 | static 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 | |||
1226 | static 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 | ||
1190 | static struct crypto_alg aesni_algs[] = { { | 1242 | static 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 | }, { |