On Saturday, October 22, 2016 12:39:26 PM CEST Chris Blake wrote: > This patch was provided by Ben at http://lists.infradead.org/pipermail > /lede-dev/2016-October/003332.html and adds ccm(aes) support to the AES-NI > acceleration. Currently it is not submitted upstream, but has been confirmed > working on the PC Engines APU2 using openssl. Well, I might be able to provide a bit of context for that patch and why it was never for upstream.
First, the original version can be found here: "Re: Looking for non-NIC hardware-offload for wpa2 decrypt." <http://marc.info/?l=linux-wireless&m=140767827527151> And it wasn't about openssl at all (In fact, openssl could just use AES-NI directly instead of bothering the kernel, since it's part of the x86 ISA). Instead it was a PoC that improved the performance of the software encryption/decryption in mac80211's aes_ccm.c code-path. In order to get mac80211 to pick it up as a viable aead cipher, it had to support the synchronous crypto reguests from mac80211. So most of the special code deals with setting up aes-ccm fallback (for !irq_fpu_usable() cases - used by ICMP) and the other is just the AESNI aes-ctr with parts from ccm.c. I don't think this will ever fly by the crypto folks in this form due to the CRYPTO_ALGO_ASYNC fallback parts which are necessary to get it to work with mac80211. And in case CRYPTO_ALGO_ASYNC is possible, the crypto framework will already pick up AESNI aes-ctr anyway. The real solution here would be: make mac80211 support asynchronous software encryption/decryption. This has the added benefit that it would work with other ciphers and also allow for hardware crypto devices (like the ppc4xx-crypto). And not supporting this patch. (Note: crypto API changes are a pain and "expensive"). Regards, Christian [...] > ++struct ccm_async_ctx { > ++ struct crypto_aes_ctx ctx; > ++ struct crypto_aead *fallback; > ++}; > ++[...] > ++ > ++static int ccm_init(struct crypto_aead *tfm) > ++{ > ++ struct crypto_aead *crypto_tfm; > ++ struct ccm_async_ctx *ctx = (struct ccm_async_ctx *) > ++ PTR_ALIGN((u8 *)crypto_aead_ctx(tfm), AESNI_ALIGN); > ++ > ++ crypto_tfm = crypto_alloc_aead("ccm(aes)", 0, > ++ CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK); > ++ if (IS_ERR(crypto_tfm)) > ++ return PTR_ERR(crypto_tfm); > ++ > ++ ctx->fallback = crypto_tfm; > ++ return 0; > ++} > ++ > ++static void ccm_exit(struct crypto_aead *tfm) > ++{ > ++ struct ccm_async_ctx *ctx = (struct ccm_async_ctx *) > ++ PTR_ALIGN((u8 *)crypto_aead_ctx(tfm), AESNI_ALIGN); > ++ > ++ if (!IS_ERR_OR_NULL(ctx->fallback)) > ++ crypto_free_aead(ctx->fallback); > ++} > ++ > ++static int ccm_setkey(struct crypto_aead *aead, const u8 *in_key, > ++ unsigned int key_len) > ++{ > ++ struct crypto_tfm *tfm = crypto_aead_tfm(aead); > ++ struct ccm_async_ctx *ctx = (struct ccm_async_ctx *) > ++ PTR_ALIGN((u8 *)crypto_aead_ctx(aead), AESNI_ALIGN); > ++ int err; > ++ > ++ err = __ccm_setkey(aead, in_key, key_len); > ++ if (err) > ++ return err; > ++ > ++ /* > ++ * Set the fallback transform to use the same request flags as > ++ * the hardware transform. > ++ */ > ++ ctx->fallback->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK; > ++ ctx->fallback->base.crt_flags |= > ++ tfm->crt_flags & CRYPTO_TFM_REQ_MASK; > ++ return crypto_aead_setkey(ctx->fallback, in_key, key_len); > ++} > ++ > ++static int ccm_setauthsize(struct crypto_aead *aead, unsigned int authsize) > ++{ > ++ struct ccm_async_ctx *ctx = (struct ccm_async_ctx *) > ++ PTR_ALIGN((u8 *)crypto_aead_ctx(aead), AESNI_ALIGN); > ++ int err; > ++ > ++ err = __ccm_setauthsize(aead, authsize); > ++ if (err) > ++ return err; > ++ > ++ return crypto_aead_setauthsize(ctx->fallback, authsize); > ++} > ++ > ++static int ccm_encrypt(struct aead_request *req) > ++{ > ++ int ret; > ++ > ++ if (!irq_fpu_usable()) { > ++ struct crypto_aead *aead = crypto_aead_reqtfm(req); > ++ struct ccm_async_ctx *ctx = get_ccm_ctx(aead); > ++ struct crypto_aead *fallback = ctx->fallback; > ++ > ++ char aead_req_data[sizeof(struct aead_request) + > ++ crypto_aead_reqsize(fallback)] > ++ __aligned(__alignof__(struct aead_request)); > ++ struct aead_request *aead_req = (void *) aead_req_data; > ++ > ++ memset(aead_req, 0, sizeof(aead_req_data)); > ++ aead_request_set_tfm(aead_req, fallback); > ++ aead_request_set_ad(aead_req, req->assoclen); > ++ aead_request_set_crypt(aead_req, req->src, req->dst, > ++ req->cryptlen, req->iv); > ++ aead_request_set_callback(aead_req, req->base.flags, > ++ req->base.complete, req->base.data); > ++ ret = crypto_aead_encrypt(aead_req); > ++ } else { > ++ kernel_fpu_begin(); > ++ ret = __ccm_encrypt(req); > ++ kernel_fpu_end(); > ++ } > ++ return ret; > ++} > ++ > ++static int ccm_decrypt(struct aead_request *req) > ++{ > ++ int ret; > ++ > ++ if (!irq_fpu_usable()) { > ++ struct crypto_aead *aead = crypto_aead_reqtfm(req); > ++ struct ccm_async_ctx *ctx = get_ccm_ctx(aead); > ++ struct crypto_aead *fallback = ctx->fallback; > ++ > ++ char aead_req_data[sizeof(struct aead_request) + > ++ crypto_aead_reqsize(fallback)] > ++ __aligned(__alignof__(struct aead_request)); > ++ struct aead_request *aead_req = (void *) aead_req_data; > ++ > ++ memset(aead_req, 0, sizeof(aead_req_data)); > ++ aead_request_set_tfm(aead_req, fallback); > ++ aead_request_set_ad(aead_req, req->assoclen); > ++ aead_request_set_crypt(aead_req, req->src, req->dst, > ++ req->cryptlen, req->iv); > ++ aead_request_set_callback(aead_req, req->base.flags, > ++ req->base.complete, req->base.data); > ++ ret = crypto_aead_decrypt(aead_req); > ++ } else { > ++ kernel_fpu_begin(); > ++ ret = __ccm_decrypt(req); > ++ kernel_fpu_end(); > ++ } > ++ return ret; > ++} > + #endif > + > + static int ablk_ecb_init(struct crypto_tfm *tfm) > +@@ -1437,7 +1888,45 @@ static struct aead_alg aesni_aead_algs[] = { { > + .cra_ctxsize = sizeof(struct cryptd_aead *), > + .cra_module = THIS_MODULE, > + }, > +-} }; > ++}, { > ++ .ivsize = AES_BLOCK_SIZE, > ++ .maxauthsize = AES_BLOCK_SIZE, > ++ .setkey = __ccm_setkey, > ++ .setauthsize = __ccm_setauthsize, > ++ .encrypt = __ccm_encrypt, > ++ .decrypt = __ccm_decrypt, > ++ .base = { > ++ .cra_name = "__ccm-aes-aesni", > ++ .cra_driver_name = "__driver-ccm-aes-aesni", > ++ .cra_priority = 0, > ++ .cra_flags = CRYPTO_ALG_INTERNAL, > ++ .cra_blocksize = 1, > ++ .cra_ctxsize = sizeof(struct crypto_aes_ctx) + > ++ AESNI_ALIGN - 1, > ++ .cra_alignmask = 0, > ++ .cra_module = THIS_MODULE, > ++ }, > ++}, { > ++ .base = { > ++ .cra_name = "ccm(aes)", > ++ .cra_driver_name = "ccm-aes-aesni", > ++ .cra_priority = 700, > ++ .cra_flags = CRYPTO_ALG_NEED_FALLBACK, > ++ .cra_blocksize = 1, > ++ .cra_ctxsize = AESNI_ALIGN - 1 + > ++ sizeof(struct ccm_async_ctx), > ++ .cra_alignmask = 0, > ++ .cra_module = THIS_MODULE, > ++ }, > ++ .init = ccm_init, > ++ .exit = ccm_exit, > ++ .ivsize = AES_BLOCK_SIZE, > ++ .maxauthsize = AES_BLOCK_SIZE, > ++ .setkey = ccm_setkey, > ++ .setauthsize = ccm_setauthsize, > ++ .encrypt = ccm_encrypt, > ++ .decrypt = ccm_decrypt, > ++}}; > + #else > + static struct aead_alg aesni_aead_algs[0]; > + #endif _______________________________________________ Lede-dev mailing list Lede-dev@lists.infradead.org http://lists.infradead.org/mailman/listinfo/lede-dev