From abd8f81b9252eb125122ca26944c20b3567f3460 Mon Sep 17 00:00:00 2001 From: jmg Date: Mon, 6 Jul 2015 19:30:29 +0000 Subject: Fix for non-random IV's when CRD_F_IV_PRESENT and CRD_F_IV_EXPLICIT flags are not specified... This bug was introduced in r275732... This only affects IPsec ESP only policies w/ the aesni module loaded, other subsystems specify one or both of the flags... Reviewed by: gnn, delphij, eri --- sys/crypto/aesni/aesni.c | 48 +++++++++++++++++++++++++----------------------- sys/crypto/aesni/aesni.h | 1 - 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/sys/crypto/aesni/aesni.c b/sys/crypto/aesni/aesni.c index 5559e57..7f143cb 100644 --- a/sys/crypto/aesni/aesni.c +++ b/sys/crypto/aesni/aesni.c @@ -450,6 +450,7 @@ static int aesni_cipher_process(struct aesni_session *ses, struct cryptodesc *enccrd, struct cryptodesc *authcrd, struct cryptop *crp) { + uint8_t iv[AES_BLOCK_LEN]; uint8_t tag[GMAC_DIGEST_LEN]; struct thread *td; uint8_t *buf, *authbuf; @@ -504,15 +505,23 @@ aesni_cipher_process(struct aesni_session *ses, struct cryptodesc *enccrd, break; } - /* Setup ses->iv */ - bzero(ses->iv, sizeof ses->iv); - if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0) - bcopy(enccrd->crd_iv, ses->iv, ivlen); - else if (encflag && ((enccrd->crd_flags & CRD_F_IV_PRESENT) != 0)) - arc4rand(ses->iv, ivlen, 0); - else - crypto_copydata(crp->crp_flags, crp->crp_buf, - enccrd->crd_inject, ivlen, ses->iv); + /* Setup iv */ + if (encflag) { + if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0) + bcopy(enccrd->crd_iv, iv, ivlen); + else + arc4rand(iv, ivlen, 0); + + if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) + crypto_copyback(crp->crp_flags, crp->crp_buf, + enccrd->crd_inject, ivlen, iv); + } else { + if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0) + bcopy(enccrd->crd_iv, iv, ivlen); + else + crypto_copydata(crp->crp_flags, crp->crp_buf, + enccrd->crd_inject, ivlen, iv); + } if (authcrd != NULL && !encflag) crypto_copydata(crp->crp_flags, crp->crp_buf, @@ -525,33 +534,33 @@ aesni_cipher_process(struct aesni_session *ses, struct cryptodesc *enccrd, case CRYPTO_AES_CBC: if (encflag) aesni_encrypt_cbc(ses->rounds, ses->enc_schedule, - enccrd->crd_len, buf, buf, ses->iv); + enccrd->crd_len, buf, buf, iv); else aesni_decrypt_cbc(ses->rounds, ses->dec_schedule, - enccrd->crd_len, buf, ses->iv); + enccrd->crd_len, buf, iv); break; case CRYPTO_AES_ICM: /* encryption & decryption are the same */ aesni_encrypt_icm(ses->rounds, ses->enc_schedule, - enccrd->crd_len, buf, buf, ses->iv); + enccrd->crd_len, buf, buf, iv); break; case CRYPTO_AES_XTS: if (encflag) aesni_encrypt_xts(ses->rounds, ses->enc_schedule, ses->xts_schedule, enccrd->crd_len, buf, buf, - ses->iv); + iv); else aesni_decrypt_xts(ses->rounds, ses->dec_schedule, ses->xts_schedule, enccrd->crd_len, buf, buf, - ses->iv); + iv); break; case CRYPTO_AES_NIST_GCM_16: if (encflag) - AES_GCM_encrypt(buf, buf, authbuf, ses->iv, tag, + AES_GCM_encrypt(buf, buf, authbuf, iv, tag, enccrd->crd_len, authcrd->crd_len, ivlen, ses->enc_schedule, ses->rounds); else { - if (!AES_GCM_decrypt(buf, buf, authbuf, ses->iv, tag, + if (!AES_GCM_decrypt(buf, buf, authbuf, iv, tag, enccrd->crd_len, authcrd->crd_len, ivlen, ses->enc_schedule, ses->rounds)) error = EBADMSG; @@ -563,13 +572,6 @@ aesni_cipher_process(struct aesni_session *ses, struct cryptodesc *enccrd, crypto_copyback(crp->crp_flags, crp->crp_buf, enccrd->crd_skip, enccrd->crd_len, buf); - /* - * OpenBSD doesn't copy this back. This primes the IV for the next - * chain. Why do we not do it for decrypt? - */ - if (encflag && enccrd->crd_alg == CRYPTO_AES_CBC) - bcopy(buf + enccrd->crd_len - AES_BLOCK_LEN, ses->iv, AES_BLOCK_LEN); - if (!error && authcrd != NULL) { crypto_copyback(crp->crp_flags, crp->crp_buf, authcrd->crd_inject, GMAC_DIGEST_LEN, tag); diff --git a/sys/crypto/aesni/aesni.h b/sys/crypto/aesni/aesni.h index 5cd8925..2210f7f 100644 --- a/sys/crypto/aesni/aesni.h +++ b/sys/crypto/aesni/aesni.h @@ -56,7 +56,6 @@ struct aesni_session { uint8_t enc_schedule[AES_SCHED_LEN] __aligned(16); uint8_t dec_schedule[AES_SCHED_LEN] __aligned(16); uint8_t xts_schedule[AES_SCHED_LEN] __aligned(16); - uint8_t iv[AES_BLOCK_LEN]; int algo; int rounds; /* uint8_t *ses_ictx; */ -- cgit v1.1