Change return types of hash update functions in SHA-NI

r359374 introduced crypto_apply function which takes as argument a function pointer
that is expected to return an int, however aesni hash update functions
return void.
Because of that the function pointer passed was simply cast with
its return value changed.
This resulted in undefined behavior, in particular when mbuf is used, (ipsec)
m_apply checks return value of function pointer passed to it
and in our case bogusly fails after calculating hash of the first mbuf
in chain.
Fix it by changing signatures of sha update routines in aesni and
dropping the casts.

Submitted by: Kornel Duleba
Reviewed by: jhb, cem
Obtained from: Semihalf
Sponsored by: Stormshield
Differential Revision: https://reviews.freebsd.org/D25030
This commit is contained in:
Marcin Wojtas 2020-05-28 09:13:20 +00:00
parent 4ac6682cab
commit ccbaa67d8b
2 changed files with 16 additions and 19 deletions

View File

@ -386,8 +386,8 @@ DRIVER_MODULE(aesni, nexus, aesni_driver, aesni_devclass, 0, 0);
MODULE_VERSION(aesni, 1);
MODULE_DEPEND(aesni, crypto, 1, 1, 1);
static void
intel_sha1_update(void *vctx, const void *vdata, u_int datalen)
static int
intel_sha1_update(void *vctx, void *vdata, u_int datalen)
{
struct sha1_ctxt *ctx = vctx;
const char *data = vdata;
@ -419,6 +419,8 @@ intel_sha1_update(void *vctx, const void *vdata, u_int datalen)
intel_sha1_step(ctx->h.b32, (void *)ctx->m.b8, 1);
off += copysiz;
}
return (0);
}
static void
@ -433,8 +435,8 @@ SHA1_Finalize_fn(void *digest, void *ctx)
sha1_result(ctx, digest);
}
static void
intel_sha256_update(void *vctx, const void *vdata, u_int len)
static int
intel_sha256_update(void *vctx, void *vdata, u_int len)
{
SHA256_CTX *ctx = vctx;
uint64_t bitlen;
@ -454,7 +456,7 @@ intel_sha256_update(void *vctx, const void *vdata, u_int len)
/* Handle the case where we don't need to perform any transforms */
if (len < 64 - r) {
memcpy(&ctx->buf[r], src, len);
return;
return (0);
}
/* Finish the current block */
@ -473,6 +475,8 @@ intel_sha256_update(void *vctx, const void *vdata, u_int len)
/* Copy left over data into buffer */
memcpy(ctx->buf, src, len);
return (0);
}
static void
@ -844,20 +848,16 @@ aesni_cipher_mac(struct aesni_session *ses, struct cryptop *crp,
ses->hash_update(&sctx, hmac_key, sizeof(hmac_key));
crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
__DECONST(int (*)(void *, void *, u_int), ses->hash_update),
&sctx);
ses->hash_update, &sctx);
if (CRYPTO_HAS_OUTPUT_BUFFER(crp) &&
CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
crypto_apply_buf(&crp->crp_obuf,
crp->crp_payload_output_start,
crp->crp_payload_length,
__DECONST(int (*)(void *, void *, u_int),
ses->hash_update), &sctx);
ses->hash_update, &sctx);
else
crypto_apply(crp, crp->crp_payload_start,
crp->crp_payload_length,
__DECONST(int (*)(void *, void *, u_int),
ses->hash_update), &sctx);
crp->crp_payload_length, ses->hash_update, &sctx);
ses->hash_finalize(res, &sctx);
/* Outer hash: (K ^ OPAD) || inner hash */
@ -873,20 +873,17 @@ aesni_cipher_mac(struct aesni_session *ses, struct cryptop *crp,
ses->hash_init(&sctx);
crypto_apply(crp, crp->crp_aad_start, crp->crp_aad_length,
__DECONST(int (*)(void *, void *, u_int), ses->hash_update),
&sctx);
ses->hash_update, &sctx);
if (CRYPTO_HAS_OUTPUT_BUFFER(crp) &&
CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
crypto_apply_buf(&crp->crp_obuf,
crp->crp_payload_output_start,
crp->crp_payload_length,
__DECONST(int (*)(void *, void *, u_int),
ses->hash_update), &sctx);
ses->hash_update, &sctx);
else
crypto_apply(crp, crp->crp_payload_start,
crp->crp_payload_length,
__DECONST(int (*)(void *, void *, u_int),
ses->hash_update), &sctx);
ses->hash_update, &sctx);
ses->hash_finalize(res, &sctx);
}

View File

@ -63,7 +63,7 @@ struct aesni_session {
int mlen;
int hash_len;
void (*hash_init)(void *);
void (*hash_update)(void *, const void *, unsigned);
int (*hash_update)(void *, void *, unsigned);
void (*hash_finalize)(void *, void *);
bool hmac;
};