Index: sys/crypto/aesni/aesni.c =================================================================== --- sys/crypto/aesni/aesni.c +++ sys/crypto/aesni/aesni.c @@ -347,16 +347,38 @@ aesni_cipher_alloc(struct cryptop *crp, int start, int length, bool *allocated) { uint8_t *addr; - - addr = crypto_contiguous_subsegment(crp, start, length); - if (addr != NULL) { - *allocated = false; - return (addr); + int totallen, iskip, oskip; + iskip = oskip = 0; + + if (!(crp->crp_flags & CRYPTO_F_ESN)) { + addr = crypto_contiguous_subsegment(crp, start, length); + if (addr != NULL) { + *allocated = false; + return (addr); + } } - addr = malloc(length, M_AESNI, M_NOWAIT); + + totallen = length; + if (crp->crp_flags & CRYPTO_F_ESN && (start == crp->crp_aad_start)) + totallen += 4; + + addr = malloc(totallen, M_AESNI, M_NOWAIT); if (addr != NULL) { *allocated = true; - crypto_copydata(crp, start, length, addr); + if (crp->crp_flags & CRYPTO_F_ESN && (start == crp->crp_aad_start)) { + /* + * According to RFC4106, AAD in GCM mode consists of + * data that are not encrypted: SPI, + * ESN (only when enabled) and Sequence number + */ + /* SPI */ + crypto_copydata(crp, start, 4, addr); + iskip = 4; + /* ESN */ + bcopy(crp->crp_esn, addr + 4, 4); + oskip = iskip + 4; + } + crypto_copydata(crp, start + iskip, length - iskip, addr + oskip); } else *allocated = false; return (addr); @@ -678,7 +700,7 @@ const struct crypto_session_params *csp) { uint8_t iv[AES_BLOCK_LEN], tag[GMAC_DIGEST_LEN], *buf, *authbuf; - int error; + int error, authlen; bool encflag, allocated, authallocated; buf = aesni_cipher_alloc(crp, crp->crp_payload_start, @@ -688,6 +710,7 @@ authallocated = false; authbuf = NULL; + authlen = 0; if (csp->csp_cipher_alg == CRYPTO_AES_NIST_GCM_16 || csp->csp_cipher_alg == CRYPTO_AES_CCM_16) { authbuf = aesni_cipher_alloc(crp, crp->crp_aad_start, @@ -696,6 +719,10 @@ error = ENOMEM; goto out; } + + authlen = crp->crp_aad_length; + if (crp->crp_flags & CRYPTO_F_ESN) + authlen += 4; } error = 0; @@ -734,7 +761,7 @@ if (encflag) { memset(tag, 0, sizeof(tag)); AES_GCM_encrypt(buf, buf, authbuf, iv, tag, - crp->crp_payload_length, crp->crp_aad_length, + crp->crp_payload_length, authlen, csp->csp_ivlen, ses->enc_schedule, ses->rounds); crypto_copyback(crp, crp->crp_digest_start, sizeof(tag), tag); @@ -742,7 +769,7 @@ crypto_copydata(crp, crp->crp_digest_start, sizeof(tag), tag); if (!AES_GCM_decrypt(buf, buf, authbuf, iv, tag, - crp->crp_payload_length, crp->crp_aad_length, + crp->crp_payload_length, authlen, csp->csp_ivlen, ses->enc_schedule, ses->rounds)) error = EBADMSG; } @@ -751,7 +778,7 @@ if (encflag) { memset(tag, 0, sizeof(tag)); AES_CCM_encrypt(buf, buf, authbuf, iv, tag, - crp->crp_payload_length, crp->crp_aad_length, + crp->crp_payload_length, authlen, csp->csp_ivlen, ses->enc_schedule, ses->rounds); crypto_copyback(crp, crp->crp_digest_start, sizeof(tag), tag); @@ -759,7 +786,7 @@ crypto_copydata(crp, crp->crp_digest_start, sizeof(tag), tag); if (!AES_CCM_decrypt(buf, buf, authbuf, iv, tag, - crp->crp_payload_length, crp->crp_aad_length, + crp->crp_payload_length, authlen, csp->csp_ivlen, ses->enc_schedule, ses->rounds)) error = EBADMSG; } @@ -775,7 +802,7 @@ free(buf, M_AESNI); } if (authallocated) { - explicit_bzero(authbuf, crp->crp_aad_length); + explicit_bzero(authbuf, authlen); free(authbuf, M_AESNI); } return (error); @@ -817,6 +844,10 @@ crp->crp_payload_length, __DECONST(int (*)(void *, void *, u_int), ses->hash_update), &sctx); + + if (crp->crp_flags & CRYPTO_F_ESN) + ses->hash_update(&sctx, crp->crp_esn, 4); + ses->hash_finalize(res, &sctx); /* Outer hash: (K ^ OPAD) || inner hash */