[LEDE-DEV] [RFC 4/6 v2] Generic: Crypto - aesni - add ccm(aes) algorithm implementation

Chris Blake chrisrblake93 at gmail.com
Sun Oct 23 02:56:51 PDT 2016


Christian,

Thanks for the information. This patch will be removed from the next RFC.

- Chris Blake

On Sat, Oct 22, 2016 at 2:12 PM, Christian Lamparter
<chunkeey at googlemail.com> wrote:
> 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
>



More information about the Lede-dev mailing list