Add explicit bzero's of sensitive data in software crypto consumers.

Explicitly zero IVs, block buffers, and hashes/digests.

Reviewed by:	delphij
Sponsored by:	Netflix
Differential Revision:	https://reviews.freebsd.org/D25057
This commit is contained in:
John Baldwin 2020-06-03 22:11:05 +00:00
parent 0897babceb
commit 20c128da91
2 changed files with 68 additions and 23 deletions

View File

@ -1495,11 +1495,15 @@ ccr_gcm_soft(struct ccr_session *s, struct cryptop *crp)
} }
} else } else
error = EBADMSG; error = EBADMSG;
explicit_bzero(digest2, sizeof(digest2));
} }
out: out:
zfree(kschedule, M_CCR); zfree(kschedule, M_CCR);
zfree(auth_ctx, M_CCR); zfree(auth_ctx, M_CCR);
explicit_bzero(block, sizeof(block));
explicit_bzero(iv, sizeof(iv));
explicit_bzero(digest, sizeof(digest));
crp->crp_etype = error; crp->crp_etype = error;
crypto_done(crp); crypto_done(crp);
} }
@ -1953,11 +1957,15 @@ ccr_ccm_soft(struct ccr_session *s, struct cryptop *crp)
} }
} else } else
error = EBADMSG; error = EBADMSG;
explicit_bzero(digest2, sizeof(digest2));
} }
out: out:
zfree(kschedule, M_CCR); zfree(kschedule, M_CCR);
zfree(auth_ctx, M_CCR); zfree(auth_ctx, M_CCR);
explicit_bzero(block, sizeof(block));
explicit_bzero(iv, sizeof(iv));
explicit_bzero(digest, sizeof(digest));
crp->crp_etype = error; crp->crp_etype = error;
crypto_done(crp); crypto_done(crp);
} }

View File

@ -131,8 +131,6 @@ swcr_encdec(struct swcr_session *ses, struct cryptop *crp)
(crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0) (crp->crp_flags & CRYPTO_F_IV_SEPARATE) == 0)
return (EINVAL); return (EINVAL);
crypto_read_iv(crp, iv);
if (crp->crp_cipher_key != NULL) { if (crp->crp_cipher_key != NULL) {
csp = crypto_get_params(crp->crp_session); csp = crypto_get_params(crp->crp_session);
error = exf->setkey(sw->sw_kschedule, error = exf->setkey(sw->sw_kschedule,
@ -141,6 +139,8 @@ swcr_encdec(struct swcr_session *ses, struct cryptop *crp)
return (error); return (error);
} }
crypto_read_iv(crp, iv);
if (exf->reinit) { if (exf->reinit) {
/* /*
* xforms that provide a reinit method perform all IV * xforms that provide a reinit method perform all IV
@ -277,6 +277,9 @@ swcr_encdec(struct swcr_session *ses, struct cryptop *crp)
crypto_cursor_copyback(&cc_out, resid, blk); crypto_cursor_copyback(&cc_out, resid, blk);
} }
explicit_bzero(blk, sizeof(blk));
explicit_bzero(iv, sizeof(iv));
explicit_bzero(iv2, sizeof(iv2));
return (0); return (0);
} }
@ -314,7 +317,6 @@ static int
swcr_authcompute(struct swcr_session *ses, struct cryptop *crp) swcr_authcompute(struct swcr_session *ses, struct cryptop *crp)
{ {
u_char aalg[HASH_MAX_LEN]; u_char aalg[HASH_MAX_LEN];
u_char uaalg[HASH_MAX_LEN];
const struct crypto_session_params *csp; const struct crypto_session_params *csp;
struct swcr_auth *sw; struct swcr_auth *sw;
struct auth_hash *axf; struct auth_hash *axf;
@ -383,14 +385,18 @@ swcr_authcompute(struct swcr_session *ses, struct cryptop *crp)
} }
if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
u_char uaalg[HASH_MAX_LEN];
crypto_copydata(crp, crp->crp_digest_start, sw->sw_mlen, uaalg); crypto_copydata(crp, crp->crp_digest_start, sw->sw_mlen, uaalg);
if (timingsafe_bcmp(aalg, uaalg, sw->sw_mlen) != 0) if (timingsafe_bcmp(aalg, uaalg, sw->sw_mlen) != 0)
return (EBADMSG); err = EBADMSG;
explicit_bzero(uaalg, sizeof(uaalg));
} else { } else {
/* Inject the authentication data */ /* Inject the authentication data */
crypto_copyback(crp, crp->crp_digest_start, sw->sw_mlen, aalg); crypto_copyback(crp, crp->crp_digest_start, sw->sw_mlen, aalg);
} }
return (0); explicit_bzero(aalg, sizeof(aalg));
return (err);
} }
CTASSERT(INT_MAX <= (1ll<<39) - 256); /* GCM: plain text < 2^39-256 */ CTASSERT(INT_MAX <= (1ll<<39) - 256); /* GCM: plain text < 2^39-256 */
@ -402,14 +408,13 @@ swcr_gmac(struct swcr_session *ses, struct cryptop *crp)
uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))]; uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))];
u_char *blk = (u_char *)blkbuf; u_char *blk = (u_char *)blkbuf;
u_char aalg[AALG_MAX_RESULT_LEN]; u_char aalg[AALG_MAX_RESULT_LEN];
u_char uaalg[AALG_MAX_RESULT_LEN];
u_char iv[EALG_MAX_BLOCK_LEN]; u_char iv[EALG_MAX_BLOCK_LEN];
struct crypto_buffer_cursor cc; struct crypto_buffer_cursor cc;
union authctx ctx; union authctx ctx;
struct swcr_auth *swa; struct swcr_auth *swa;
struct auth_hash *axf; struct auth_hash *axf;
uint32_t *blkp; uint32_t *blkp;
int blksz, ivlen, len, resid; int blksz, error, ivlen, len, resid;
swa = &ses->swcr_auth; swa = &ses->swcr_auth;
axf = swa->sw_axf; axf = swa->sw_axf;
@ -440,16 +445,23 @@ swcr_gmac(struct swcr_session *ses, struct cryptop *crp)
/* Finalize MAC */ /* Finalize MAC */
axf->Final(aalg, &ctx); axf->Final(aalg, &ctx);
error = 0;
if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
u_char uaalg[AALG_MAX_RESULT_LEN];
crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
uaalg); uaalg);
if (timingsafe_bcmp(aalg, uaalg, swa->sw_mlen) != 0) if (timingsafe_bcmp(aalg, uaalg, swa->sw_mlen) != 0)
return (EBADMSG); error = EBADMSG;
explicit_bzero(uaalg, sizeof(uaalg));
} else { } else {
/* Inject the authentication data */ /* Inject the authentication data */
crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, aalg); crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, aalg);
} }
return (0); explicit_bzero(blkbuf, sizeof(blkbuf));
explicit_bzero(aalg, sizeof(aalg));
explicit_bzero(iv, sizeof(iv));
return (error);
} }
static int static int
@ -458,7 +470,6 @@ swcr_gcm(struct swcr_session *ses, struct cryptop *crp)
uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))]; uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))];
u_char *blk = (u_char *)blkbuf; u_char *blk = (u_char *)blkbuf;
u_char aalg[AALG_MAX_RESULT_LEN]; u_char aalg[AALG_MAX_RESULT_LEN];
u_char uaalg[AALG_MAX_RESULT_LEN];
u_char iv[EALG_MAX_BLOCK_LEN]; u_char iv[EALG_MAX_BLOCK_LEN];
struct crypto_buffer_cursor cc_in, cc_out; struct crypto_buffer_cursor cc_in, cc_out;
union authctx ctx; union authctx ctx;
@ -467,7 +478,7 @@ swcr_gcm(struct swcr_session *ses, struct cryptop *crp)
struct auth_hash *axf; struct auth_hash *axf;
struct enc_xform *exf; struct enc_xform *exf;
uint32_t *blkp; uint32_t *blkp;
int blksz, ivlen, len, r, resid; int blksz, error, ivlen, len, r, resid;
swa = &ses->swcr_auth; swa = &ses->swcr_auth;
axf = swa->sw_axf; axf = swa->sw_axf;
@ -536,13 +547,19 @@ swcr_gcm(struct swcr_session *ses, struct cryptop *crp)
axf->Final(aalg, &ctx); axf->Final(aalg, &ctx);
/* Validate tag */ /* Validate tag */
error = 0;
if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
u_char uaalg[AALG_MAX_RESULT_LEN];
crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
uaalg); uaalg);
r = timingsafe_bcmp(aalg, uaalg, swa->sw_mlen); r = timingsafe_bcmp(aalg, uaalg, swa->sw_mlen);
if (r != 0) explicit_bzero(uaalg, sizeof(uaalg));
return (EBADMSG); if (r != 0) {
error = EBADMSG;
goto out;
}
/* tag matches, decrypt data */ /* tag matches, decrypt data */
crypto_cursor_init(&cc_in, &crp->crp_buf); crypto_cursor_init(&cc_in, &crp->crp_buf);
@ -562,7 +579,12 @@ swcr_gcm(struct swcr_session *ses, struct cryptop *crp)
aalg); aalg);
} }
return (0); out:
explicit_bzero(blkbuf, sizeof(blkbuf));
explicit_bzero(aalg, sizeof(aalg));
explicit_bzero(iv, sizeof(iv));
return (error);
} }
static int static int
@ -571,13 +593,12 @@ swcr_ccm_cbc_mac(struct swcr_session *ses, struct cryptop *crp)
uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))]; uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))];
u_char *blk = (u_char *)blkbuf; u_char *blk = (u_char *)blkbuf;
u_char aalg[AALG_MAX_RESULT_LEN]; u_char aalg[AALG_MAX_RESULT_LEN];
u_char uaalg[AALG_MAX_RESULT_LEN];
u_char iv[EALG_MAX_BLOCK_LEN]; u_char iv[EALG_MAX_BLOCK_LEN];
struct crypto_buffer_cursor cc; struct crypto_buffer_cursor cc;
union authctx ctx; union authctx ctx;
struct swcr_auth *swa; struct swcr_auth *swa;
struct auth_hash *axf; struct auth_hash *axf;
int blksz, ivlen, len, resid; int blksz, error, ivlen, len, resid;
swa = &ses->swcr_auth; swa = &ses->swcr_auth;
axf = swa->sw_axf; axf = swa->sw_axf;
@ -609,16 +630,23 @@ swcr_ccm_cbc_mac(struct swcr_session *ses, struct cryptop *crp)
/* Finalize MAC */ /* Finalize MAC */
axf->Final(aalg, &ctx); axf->Final(aalg, &ctx);
error = 0;
if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) { if (crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) {
u_char uaalg[AALG_MAX_RESULT_LEN];
crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
uaalg); uaalg);
if (timingsafe_bcmp(aalg, uaalg, swa->sw_mlen) != 0) if (timingsafe_bcmp(aalg, uaalg, swa->sw_mlen) != 0)
return (EBADMSG); error = EBADMSG;
explicit_bzero(uaalg, sizeof(uaalg));
} else { } else {
/* Inject the authentication data */ /* Inject the authentication data */
crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, aalg); crypto_copyback(crp, crp->crp_digest_start, swa->sw_mlen, aalg);
} }
return (0); explicit_bzero(blkbuf, sizeof(blkbuf));
explicit_bzero(aalg, sizeof(aalg));
explicit_bzero(iv, sizeof(iv));
return (error);
} }
static int static int
@ -627,7 +655,6 @@ swcr_ccm(struct swcr_session *ses, struct cryptop *crp)
uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))]; uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))];
u_char *blk = (u_char *)blkbuf; u_char *blk = (u_char *)blkbuf;
u_char aalg[AALG_MAX_RESULT_LEN]; u_char aalg[AALG_MAX_RESULT_LEN];
u_char uaalg[AALG_MAX_RESULT_LEN];
u_char iv[EALG_MAX_BLOCK_LEN]; u_char iv[EALG_MAX_BLOCK_LEN];
struct crypto_buffer_cursor cc_in, cc_out; struct crypto_buffer_cursor cc_in, cc_out;
union authctx ctx; union authctx ctx;
@ -635,7 +662,7 @@ swcr_ccm(struct swcr_session *ses, struct cryptop *crp)
struct swcr_encdec *swe; struct swcr_encdec *swe;
struct auth_hash *axf; struct auth_hash *axf;
struct enc_xform *exf; struct enc_xform *exf;
int blksz, ivlen, len, r, resid; int blksz, error, ivlen, len, r, resid;
swa = &ses->swcr_auth; swa = &ses->swcr_auth;
axf = swa->sw_axf; axf = swa->sw_axf;
@ -712,13 +739,19 @@ swcr_ccm(struct swcr_session *ses, struct cryptop *crp)
axf->Final(aalg, &ctx); axf->Final(aalg, &ctx);
/* Validate tag */ /* Validate tag */
error = 0;
if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) { if (!CRYPTO_OP_IS_ENCRYPT(crp->crp_op)) {
u_char uaalg[AALG_MAX_RESULT_LEN];
crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen, crypto_copydata(crp, crp->crp_digest_start, swa->sw_mlen,
uaalg); uaalg);
r = timingsafe_bcmp(aalg, uaalg, swa->sw_mlen); r = timingsafe_bcmp(aalg, uaalg, swa->sw_mlen);
if (r != 0) explicit_bzero(uaalg, sizeof(uaalg));
return (EBADMSG); if (r != 0) {
error = EBADMSG;
goto out;
}
/* tag matches, decrypt data */ /* tag matches, decrypt data */
exf->reinit(swe->sw_kschedule, iv); exf->reinit(swe->sw_kschedule, iv);
@ -739,7 +772,11 @@ swcr_ccm(struct swcr_session *ses, struct cryptop *crp)
aalg); aalg);
} }
return (0); out:
explicit_bzero(blkbuf, sizeof(blkbuf));
explicit_bzero(aalg, sizeof(aalg));
explicit_bzero(iv, sizeof(iv));
return (error);
} }
/* /*