|
45 | 45 | defined(LINUXKM_LKCAPI_REGISTER_AESOFB) || \ |
46 | 46 | defined(LINUXKM_LKCAPI_REGISTER_AESECB) || \ |
47 | 47 | defined(LINUXKM_LKCAPI_REGISTER_AESCMAC) || \ |
| 48 | + defined(LINUXKM_LKCAPI_REGISTER_AESDIRECT) || \ |
48 | 49 | defined(LINUXKM_LKCAPI_REGISTER_AES_ALL) |
49 | 50 |
|
50 | 51 | #ifdef NO_AES |
|
106 | 107 | #define WOLFKM_AESOFB_NAME "ofb(aes)" |
107 | 108 | #define WOLFKM_AESECB_NAME "ecb(aes)" |
108 | 109 | #define WOLFKM_AESCMAC_NAME "cmac(aes)" |
| 110 | +#define WOLFKM_AESDIRECT_NAME "aes" |
109 | 111 |
|
110 | 112 | #if defined(WOLFSSL_X86_64_BUILD) && (defined(USE_INTEL_SPEEDUP) || defined(USE_INTEL_SPEEDUP_FOR_AES)) |
111 | 113 | #if !defined(NO_AVX512_SUPPORT) |
|
137 | 139 | #define WOLFKM_AESOFB_DRIVER ("ofb-aes" WOLFKM_AES_DRIVER_SUFFIX) |
138 | 140 | #define WOLFKM_AESECB_DRIVER ("ecb-aes" WOLFKM_AES_DRIVER_SUFFIX) |
139 | 141 | #define WOLFKM_AESCMAC_DRIVER ("cmac-aes" WOLFKM_AES_DRIVER_SUFFIX) |
| 142 | +#define WOLFKM_AESDIRECT_DRIVER ("aes" WOLFKM_AES_DRIVER_SUFFIX) |
140 | 143 |
|
141 | 144 | #ifdef HAVE_AES_CBC |
142 | 145 | #if (defined(LINUXKM_LKCAPI_REGISTER_ALL) || \ |
|
279 | 282 | #endif |
280 | 283 | #undef LINUXKM_LKCAPI_REGISTER_AESCMAC |
281 | 284 | #endif |
| 285 | +/* Bare single-block "aes" (crypto_cipher), used directly by templates such as |
| 286 | + * essiv(cbc(aes),sha256), which encrypts each sector IV with it. Without it, |
| 287 | + * dm-crypt aes-cbc-essiv volumes run IV generation outside wolfCrypt. |
| 288 | + * cia_decrypt calls wc_AesEcbDecrypt(), so decryption support is required. |
| 289 | + */ |
| 290 | +#if defined(HAVE_AES_ECB) && defined(HAVE_AES_DECRYPT) |
| 291 | + #if (defined(LINUXKM_LKCAPI_REGISTER_ALL) || \ |
| 292 | + defined(LINUXKM_LKCAPI_REGISTER_AES_ALL) || \ |
| 293 | + (defined(LINUXKM_LKCAPI_REGISTER_ALL_KCONFIG) && defined(CONFIG_CRYPTO_AES))) && \ |
| 294 | + !defined(LINUXKM_LKCAPI_DONT_REGISTER_AESDIRECT) && \ |
| 295 | + !defined(LINUXKM_LKCAPI_REGISTER_AESDIRECT) |
| 296 | + #define LINUXKM_LKCAPI_REGISTER_AESDIRECT |
| 297 | + #endif |
| 298 | +#else |
| 299 | + #undef LINUXKM_LKCAPI_REGISTER_AESDIRECT |
| 300 | +#endif |
282 | 301 |
|
283 | 302 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)) && defined(LINUXKM_LKCAPI_REGISTER_AESCMAC) |
284 | 303 | #error LINUXKM_LKCAPI_REGISTER for AES-CMAC is supported only on Linux kernel versions >= 5.6.0. |
|
321 | 340 | #ifdef LINUXKM_LKCAPI_REGISTER_AESCMAC |
322 | 341 | static int linuxkm_test_aescmac(void); |
323 | 342 | #endif |
| 343 | +#ifdef LINUXKM_LKCAPI_REGISTER_AESDIRECT |
| 344 | + static int linuxkm_test_aesdirect(void); |
| 345 | +#endif |
324 | 346 |
|
325 | 347 | #if defined(LINUXKM_LKCAPI_REGISTER_AESCBC) || \ |
326 | 348 | defined(LINUXKM_LKCAPI_REGISTER_AESCFB) || \ |
327 | 349 | defined(LINUXKM_LKCAPI_REGISTER_AESCTR) || \ |
328 | 350 | defined(LINUXKM_LKCAPI_REGISTER_AESOFB) || \ |
329 | 351 | defined(LINUXKM_LKCAPI_REGISTER_AESECB) || \ |
| 352 | + defined(LINUXKM_LKCAPI_REGISTER_AESDIRECT) || \ |
330 | 353 | defined(LINUXKM_LKCAPI_REGISTER_AESGCM) || \ |
331 | 354 | defined(LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106) || \ |
332 | 355 | defined(LINUXKM_LKCAPI_REGISTER_AESCCM) || \ |
|
342 | 365 | #define LINUXKM_LKCAPI_NEED_AES_SKCIPHER_COMMON_FUNCS |
343 | 366 | #endif |
344 | 367 |
|
| 368 | +#if defined(LINUXKM_LKCAPI_NEED_AES_SKCIPHER_COMMON_FUNCS) || \ |
| 369 | + defined(LINUXKM_LKCAPI_REGISTER_AESDIRECT) |
| 370 | + #define LINUXKM_LKCAPI_NEED_AES_SETKEY_COMMON_FUNCS |
| 371 | +#endif |
| 372 | + |
345 | 373 | #if defined(LINUXKM_LKCAPI_REGISTER_AESGCM) || \ |
346 | 374 | defined(LINUXKM_LKCAPI_REGISTER_AESGCM_RFC4106) || \ |
347 | 375 | defined(LINUXKM_LKCAPI_REGISTER_AESCCM) || \ |
@@ -580,7 +608,7 @@ static void km_AesExitCommon(struct km_AesCtx * ctx) |
580 | 608 | #endif /* WOLFKM_DEBUG_AES */ |
581 | 609 | } |
582 | 610 |
|
583 | | -#ifdef LINUXKM_LKCAPI_NEED_AES_SKCIPHER_COMMON_FUNCS |
| 611 | +#ifdef LINUXKM_LKCAPI_NEED_AES_SETKEY_COMMON_FUNCS |
584 | 612 |
|
585 | 613 | static int km_AesSetKeyCommon(struct km_AesCtx * ctx, const u8 *in_key, |
586 | 614 | unsigned int key_len, const char * name) |
@@ -650,6 +678,10 @@ static int km_AesSetKeyCommon(struct km_AesCtx * ctx, const u8 *in_key, |
650 | 678 | return 0; |
651 | 679 | } |
652 | 680 |
|
| 681 | +#endif /* LINUXKM_LKCAPI_NEED_AES_SETKEY_COMMON_FUNCS */ |
| 682 | + |
| 683 | +#ifdef LINUXKM_LKCAPI_NEED_AES_SKCIPHER_COMMON_FUNCS |
| 684 | + |
653 | 685 | static void km_AesExit(struct crypto_skcipher *tfm) |
654 | 686 | { |
655 | 687 | struct km_AesCtx * ctx = crypto_skcipher_ctx(tfm); |
@@ -3258,6 +3290,112 @@ static int ecbAesAlg_loaded = 0; |
3258 | 3290 |
|
3259 | 3291 | #endif /* LINUXKM_LKCAPI_REGISTER_AESECB */ |
3260 | 3292 |
|
| 3293 | +#ifdef LINUXKM_LKCAPI_REGISTER_AESDIRECT |
| 3294 | + |
| 3295 | +/* crypto_cipher_setkey() and crypto_cipher_{en,de}crypt_one(), used by the |
| 3296 | + * self-test, are in the CRYPTO_INTERNAL namespace since 5.12. |
| 3297 | + */ |
| 3298 | +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0) |
| 3299 | + MODULE_IMPORT_NS("CRYPTO_INTERNAL"); |
| 3300 | +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) |
| 3301 | + MODULE_IMPORT_NS(CRYPTO_INTERNAL); |
| 3302 | +#endif |
| 3303 | + |
| 3304 | +/* crypto_register_alg() takes a bare struct crypto_alg; wrapping it lets |
| 3305 | + * REGISTER_ALG() and UNREGISTER_ALG(), which use (alg).base, handle it. |
| 3306 | + */ |
| 3307 | +struct km_cipher_alg { |
| 3308 | + struct crypto_alg base; |
| 3309 | +}; |
| 3310 | + |
| 3311 | +static inline int crypto_register_km_cipher(struct km_cipher_alg *alg) |
| 3312 | +{ |
| 3313 | + return crypto_register_alg(&alg->base); |
| 3314 | +} |
| 3315 | + |
| 3316 | +static inline void crypto_unregister_km_cipher(struct km_cipher_alg *alg) |
| 3317 | +{ |
| 3318 | + crypto_unregister_alg(&alg->base); |
| 3319 | +} |
| 3320 | + |
| 3321 | +static int km_AesDirectInit(struct crypto_tfm *tfm) |
| 3322 | +{ |
| 3323 | + struct km_AesCtx * ctx = crypto_tfm_ctx(tfm); |
| 3324 | + return km_AesInitCommon(ctx, WOLFKM_AESDIRECT_DRIVER, 1); |
| 3325 | +} |
| 3326 | + |
| 3327 | +static void km_AesDirectExit(struct crypto_tfm *tfm) |
| 3328 | +{ |
| 3329 | + struct km_AesCtx * ctx = crypto_tfm_ctx(tfm); |
| 3330 | + km_AesExitCommon(ctx); |
| 3331 | +} |
| 3332 | + |
| 3333 | +static int km_AesDirectSetKey(struct crypto_tfm *tfm, const u8 *in_key, |
| 3334 | + unsigned int key_len) |
| 3335 | +{ |
| 3336 | + struct km_AesCtx * ctx = crypto_tfm_ctx(tfm); |
| 3337 | + return km_AesSetKeyCommon(ctx, in_key, key_len, WOLFKM_AESDIRECT_DRIVER); |
| 3338 | +} |
| 3339 | + |
| 3340 | +/* One block, through the same wc_AesEcb*() calls and shared key schedule |
| 3341 | + * (copy_p 0) as ecbAesAlg. cia_encrypt and cia_decrypt cannot report an |
| 3342 | + * error, so on failure the output block is zeroed rather than left unset. |
| 3343 | + */ |
| 3344 | +static void km_AesDirectCrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src, |
| 3345 | + int decrypt_p) |
| 3346 | +{ |
| 3347 | + struct km_AesCtx * ctx = crypto_tfm_ctx(tfm); |
| 3348 | + Aes *aes; |
| 3349 | + int err; |
| 3350 | + |
| 3351 | + err = km_AesGet(ctx, decrypt_p, 0 /* copy_p */, &aes); |
| 3352 | + if (likely(! err)) { |
| 3353 | + if (decrypt_p) |
| 3354 | + err = wc_AesEcbDecrypt(aes, dst, src, WC_AES_BLOCK_SIZE); |
| 3355 | + else |
| 3356 | + err = wc_AesEcbEncrypt(aes, dst, src, WC_AES_BLOCK_SIZE); |
| 3357 | + } |
| 3358 | + |
| 3359 | + if (unlikely(err)) { |
| 3360 | + pr_err_ratelimited("%s: wc_AesEcb%s failed: %d\n", |
| 3361 | + WOLFKM_AESDIRECT_DRIVER, |
| 3362 | + decrypt_p ? "Decrypt" : "Encrypt", err); |
| 3363 | + memset(dst, 0, WC_AES_BLOCK_SIZE); |
| 3364 | + } |
| 3365 | +} |
| 3366 | + |
| 3367 | +static void km_AesDirectEncrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) |
| 3368 | +{ |
| 3369 | + km_AesDirectCrypt(tfm, dst, src, 0); |
| 3370 | +} |
| 3371 | + |
| 3372 | +static void km_AesDirectDecrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) |
| 3373 | +{ |
| 3374 | + km_AesDirectCrypt(tfm, dst, src, 1); |
| 3375 | +} |
| 3376 | + |
| 3377 | +static struct km_cipher_alg aesDirectAlg = { |
| 3378 | + .base.cra_name = WOLFKM_AESDIRECT_NAME, |
| 3379 | + .base.cra_driver_name = WOLFKM_AESDIRECT_DRIVER, |
| 3380 | + .base.cra_priority = WOLFSSL_LINUXKM_LKCAPI_PRIORITY, |
| 3381 | + .base.cra_flags = CRYPTO_ALG_TYPE_CIPHER, |
| 3382 | + .base.cra_blocksize = WC_AES_BLOCK_SIZE, |
| 3383 | + .base.cra_ctxsize = sizeof(struct km_AesCtx), |
| 3384 | + .base.cra_module = THIS_MODULE, |
| 3385 | + .base.cra_init = km_AesDirectInit, |
| 3386 | + .base.cra_exit = km_AesDirectExit, |
| 3387 | + .base.cra_u.cipher = { |
| 3388 | + .cia_min_keysize = AES_128_KEY_SIZE, |
| 3389 | + .cia_max_keysize = AES_256_KEY_SIZE, |
| 3390 | + .cia_setkey = km_AesDirectSetKey, |
| 3391 | + .cia_encrypt = km_AesDirectEncrypt, |
| 3392 | + .cia_decrypt = km_AesDirectDecrypt, |
| 3393 | + }, |
| 3394 | +}; |
| 3395 | +static int aesDirectAlg_loaded = 0; |
| 3396 | + |
| 3397 | +#endif /* LINUXKM_LKCAPI_REGISTER_AESDIRECT */ |
| 3398 | + |
3261 | 3399 | /* cipher tests, cribbed from test.c, with supplementary LKCAPI tests: */ |
3262 | 3400 |
|
3263 | 3401 | #ifdef LINUXKM_LKCAPI_REGISTER_AESCBC |
@@ -5184,6 +5322,110 @@ static int linuxkm_test_aesecb(void) { |
5184 | 5322 |
|
5185 | 5323 | #endif /* LINUXKM_LKCAPI_REGISTER_AESECB */ |
5186 | 5324 |
|
| 5325 | +#ifdef LINUXKM_LKCAPI_REGISTER_AESDIRECT |
| 5326 | + |
| 5327 | +/* FIPS-197 Appendix C.1 (AES-128), C.2 (AES-192) and C.3 (AES-256) known |
| 5328 | + * answers, for the key sizes this build supports, run through the kernel API |
| 5329 | + * so the test covers the registration as well as wolfCrypt. |
| 5330 | + */ |
| 5331 | +static int linuxkm_test_aesdirect(void) { |
| 5332 | + static const u8 key[32] = { |
| 5333 | + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, |
| 5334 | + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, |
| 5335 | + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, |
| 5336 | + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f |
| 5337 | + }; |
| 5338 | + static const u8 pt[WC_AES_BLOCK_SIZE] = { |
| 5339 | + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, |
| 5340 | + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff |
| 5341 | + }; |
| 5342 | +#ifdef WOLFSSL_AES_128 |
| 5343 | + static const u8 ct128[WC_AES_BLOCK_SIZE] = { |
| 5344 | + 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, |
| 5345 | + 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a |
| 5346 | + }; |
| 5347 | +#endif |
| 5348 | +#ifdef WOLFSSL_AES_192 |
| 5349 | + static const u8 ct192[WC_AES_BLOCK_SIZE] = { |
| 5350 | + 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, |
| 5351 | + 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 |
| 5352 | + }; |
| 5353 | +#endif |
| 5354 | +#ifdef WOLFSSL_AES_256 |
| 5355 | + static const u8 ct256[WC_AES_BLOCK_SIZE] = { |
| 5356 | + 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, |
| 5357 | + 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 |
| 5358 | + }; |
| 5359 | +#endif |
| 5360 | + static const struct { |
| 5361 | + unsigned int key_len; |
| 5362 | + const u8 *ct; |
| 5363 | + } kat[] = { |
| 5364 | +#ifdef WOLFSSL_AES_128 |
| 5365 | + { AES_128_KEY_SIZE, ct128 }, |
| 5366 | +#endif |
| 5367 | +#ifdef WOLFSSL_AES_192 |
| 5368 | + { AES_192_KEY_SIZE, ct192 }, |
| 5369 | +#endif |
| 5370 | +#ifdef WOLFSSL_AES_256 |
| 5371 | + { AES_256_KEY_SIZE, ct256 }, |
| 5372 | +#endif |
| 5373 | + }; |
| 5374 | + struct crypto_cipher *tfm; |
| 5375 | + u8 buf[WC_AES_BLOCK_SIZE]; |
| 5376 | + size_t i; |
| 5377 | + int ret = 0; |
| 5378 | + |
| 5379 | + tfm = crypto_alloc_cipher(WOLFKM_AESDIRECT_NAME, 0, 0); |
| 5380 | + if (IS_ERR(tfm)) { |
| 5381 | + pr_err("error: allocating AES cipher algorithm %s failed: %d\n", |
| 5382 | + WOLFKM_AESDIRECT_DRIVER, PTR_ERR(tfm)); |
| 5383 | + return (int)PTR_ERR(tfm); |
| 5384 | + } |
| 5385 | + |
| 5386 | +#ifndef LINUXKM_LKCAPI_PRIORITY_ALLOW_MASKING |
| 5387 | + { |
| 5388 | + const char *driver_name = |
| 5389 | + crypto_tfm_alg_driver_name(crypto_cipher_tfm(tfm)); |
| 5390 | + if (strcmp(driver_name, WOLFKM_AESDIRECT_DRIVER)) { |
| 5391 | + pr_err("error: unexpected implementation for %s: %s (expected %s)\n", |
| 5392 | + WOLFKM_AESDIRECT_NAME, driver_name, WOLFKM_AESDIRECT_DRIVER); |
| 5393 | + ret = -ENOENT; |
| 5394 | + goto out; |
| 5395 | + } |
| 5396 | + } |
| 5397 | +#endif |
| 5398 | + |
| 5399 | + for (i = 0; i < sizeof(kat) / sizeof(kat[0]); ++i) { |
| 5400 | + ret = crypto_cipher_setkey(tfm, key, kat[i].key_len); |
| 5401 | + if (ret) { |
| 5402 | + pr_err("error: crypto_cipher_setkey (len %u) returned: %d\n", |
| 5403 | + kat[i].key_len, ret); |
| 5404 | + goto out; |
| 5405 | + } |
| 5406 | + crypto_cipher_encrypt_one(tfm, buf, pt); |
| 5407 | + if (memcmp(buf, kat[i].ct, sizeof(buf))) { |
| 5408 | + pr_err("error: %s AES-%u encrypt known answer mismatch\n", |
| 5409 | + WOLFKM_AESDIRECT_DRIVER, kat[i].key_len * 8); |
| 5410 | + ret = LINUXKM_LKCAPI_AES_KAT_MISMATCH_E; |
| 5411 | + goto out; |
| 5412 | + } |
| 5413 | + crypto_cipher_decrypt_one(tfm, buf, buf); |
| 5414 | + if (memcmp(buf, pt, sizeof(buf))) { |
| 5415 | + pr_err("error: %s AES-%u decrypt known answer mismatch\n", |
| 5416 | + WOLFKM_AESDIRECT_DRIVER, kat[i].key_len * 8); |
| 5417 | + ret = LINUXKM_LKCAPI_AES_KAT_MISMATCH_E; |
| 5418 | + goto out; |
| 5419 | + } |
| 5420 | + } |
| 5421 | + |
| 5422 | +out: |
| 5423 | + crypto_free_cipher(tfm); |
| 5424 | + return ret; |
| 5425 | +} |
| 5426 | + |
| 5427 | +#endif /* LINUXKM_LKCAPI_REGISTER_AESDIRECT */ |
| 5428 | + |
5187 | 5429 | #ifdef LINUXKM_LKCAPI_REGISTER_AESCMAC |
5188 | 5430 |
|
5189 | 5431 | #if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(6,0,0) |
|
0 commit comments