Changeset View
Standalone View
sys/crypto/aesni/aesni.c
Show First 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
#include <crypto/aesni/aesni.h> | #include <crypto/aesni/aesni.h> | ||||
#include <crypto/aesni/sha_sse.h> | #include <crypto/aesni/sha_sse.h> | ||||
#include <crypto/sha1.h> | #include <crypto/sha1.h> | ||||
#include <crypto/sha2/sha224.h> | #include <crypto/sha2/sha224.h> | ||||
#include <crypto/sha2/sha256.h> | #include <crypto/sha2/sha256.h> | ||||
#include <opencrypto/cryptodev.h> | #include <opencrypto/cryptodev.h> | ||||
#include <opencrypto/gmac.h> | #include <opencrypto/gmac.h> | ||||
#include <opencrypto/ccm-cbc.h> | |||||
#include <cryptodev_if.h> | #include <cryptodev_if.h> | ||||
#include <machine/md_var.h> | #include <machine/md_var.h> | ||||
#include <machine/specialreg.h> | #include <machine/specialreg.h> | ||||
#if defined(__i386__) | #if defined(__i386__) | ||||
#include <machine/npx.h> | #include <machine/npx.h> | ||||
#elif defined(__amd64__) | #elif defined(__amd64__) | ||||
#include <machine/fpu.h> | #include <machine/fpu.h> | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | aesni_probe(device_t dev) | ||||
bool has_aes, has_sha; | bool has_aes, has_sha; | ||||
detect_cpu_features(&has_aes, &has_sha); | detect_cpu_features(&has_aes, &has_sha); | ||||
if (!has_aes && !has_sha) { | if (!has_aes && !has_sha) { | ||||
device_printf(dev, "No AES or SHA support.\n"); | device_printf(dev, "No AES or SHA support.\n"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} else if (has_aes && has_sha) | } else if (has_aes && has_sha) | ||||
device_set_desc(dev, | device_set_desc(dev, | ||||
"AES-CBC,AES-XTS,AES-GCM,AES-ICM,SHA1,SHA256"); | "AES-CBC,AES-CCM,AES-GCM,AES-ICM,AES-XTS,SHA1,SHA256"); | ||||
cem: I would suggest alpha ordering here too, although XTS is out of place already. The rest are in… | |||||
else if (has_aes) | else if (has_aes) | ||||
device_set_desc(dev, "AES-CBC,AES-XTS,AES-GCM,AES-ICM"); | device_set_desc(dev, "AES-CBC,AES-XTS,AES-GCM,AES-ICM,AES-CCM"); | ||||
else | else | ||||
device_set_desc(dev, "SHA1,SHA256"); | device_set_desc(dev, "SHA1,SHA256"); | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
aesni_cleanctx(void) | aesni_cleanctx(void) | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | aesni_attach(device_t dev) | ||||
if (sc->has_aes) { | if (sc->has_aes) { | ||||
crypto_register(sc->cid, CRYPTO_AES_CBC, 0, 0); | crypto_register(sc->cid, CRYPTO_AES_CBC, 0, 0); | ||||
crypto_register(sc->cid, CRYPTO_AES_ICM, 0, 0); | crypto_register(sc->cid, CRYPTO_AES_ICM, 0, 0); | ||||
crypto_register(sc->cid, CRYPTO_AES_NIST_GCM_16, 0, 0); | crypto_register(sc->cid, CRYPTO_AES_NIST_GCM_16, 0, 0); | ||||
crypto_register(sc->cid, CRYPTO_AES_128_NIST_GMAC, 0, 0); | crypto_register(sc->cid, CRYPTO_AES_128_NIST_GMAC, 0, 0); | ||||
crypto_register(sc->cid, CRYPTO_AES_192_NIST_GMAC, 0, 0); | crypto_register(sc->cid, CRYPTO_AES_192_NIST_GMAC, 0, 0); | ||||
crypto_register(sc->cid, CRYPTO_AES_256_NIST_GMAC, 0, 0); | crypto_register(sc->cid, CRYPTO_AES_256_NIST_GMAC, 0, 0); | ||||
crypto_register(sc->cid, CRYPTO_AES_XTS, 0, 0); | crypto_register(sc->cid, CRYPTO_AES_XTS, 0, 0); | ||||
crypto_register(sc->cid, CRYPTO_AES_CCM_16, 0, 0); | |||||
Not Done Inline ActionsDoes CCM support different tag sizes ala GCM or does it always use a 16 byte tag? If the latter we don't need the _16 in its name. jhb: Does CCM support different tag sizes ala GCM or does it always use a 16 byte tag? If the… | |||||
Not Done Inline ActionsIt supports multiple sizes of tags; the tag size is related to the maximum size of the message. sef: It supports multiple sizes of tags; the tag size is related to the maximum size of the message. | |||||
crypto_register(sc->cid, CRYPTO_AES_128_CCM_CBC_MAC, 0, 0); | |||||
Not Done Inline ActionsUgh, I really hate that GCM has 3 different constants for GMAC hashes for no good reason (the sessions already get the key length, so there's really no reason for the three constants and it makes drivers do extra parameter checking). In my OCF rework I've mostly killed this though I permit it at the user API to avoid breaking compatibility. If we can just have a single CCM_CBC_MAC that would be great. jhb: Ugh, I really hate that GCM has 3 different constants for GMAC hashes for no good reason (the… | |||||
Not Done Inline ActionsThe CCM/CCB code was modeled on the GCM code, so similar changes can be applied, no doubt. sef: The CCM/CCB code was modeled on the GCM code, so similar changes can be applied, no doubt. | |||||
Not Done Inline Actions+1 cem: +1 | |||||
crypto_register(sc->cid, CRYPTO_AES_192_CCM_CBC_MAC, 0, 0); | |||||
crypto_register(sc->cid, CRYPTO_AES_256_CCM_CBC_MAC, 0, 0); | |||||
} | } | ||||
if (sc->has_sha) { | if (sc->has_sha) { | ||||
crypto_register(sc->cid, CRYPTO_SHA1, 0, 0); | crypto_register(sc->cid, CRYPTO_SHA1, 0, 0); | ||||
crypto_register(sc->cid, CRYPTO_SHA1_HMAC, 0, 0); | crypto_register(sc->cid, CRYPTO_SHA1_HMAC, 0, 0); | ||||
crypto_register(sc->cid, CRYPTO_SHA2_224, 0, 0); | crypto_register(sc->cid, CRYPTO_SHA2_224, 0, 0); | ||||
crypto_register(sc->cid, CRYPTO_SHA2_224_HMAC, 0, 0); | crypto_register(sc->cid, CRYPTO_SHA2_224_HMAC, 0, 0); | ||||
crypto_register(sc->cid, CRYPTO_SHA2_256, 0, 0); | crypto_register(sc->cid, CRYPTO_SHA2_256, 0, 0); | ||||
crypto_register(sc->cid, CRYPTO_SHA2_256_HMAC, 0, 0); | crypto_register(sc->cid, CRYPTO_SHA2_256_HMAC, 0, 0); | ||||
Show All 17 Lines | |||||
static int | static int | ||||
aesni_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) | aesni_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) | ||||
{ | { | ||||
struct aesni_softc *sc; | struct aesni_softc *sc; | ||||
struct aesni_session *ses; | struct aesni_session *ses; | ||||
struct cryptoini *encini, *authini; | struct cryptoini *encini, *authini; | ||||
bool gcm_hash, gcm; | bool gcm_hash, gcm; | ||||
bool cbc_hash, ccm; | |||||
int error; | int error; | ||||
KASSERT(cses != NULL, ("EDOOFUS")); | KASSERT(cses != NULL, ("EDOOFUS")); | ||||
if (cri == NULL) { | if (cri == NULL) { | ||||
CRYPTDEB("no cri"); | CRYPTDEB("no cri"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
ses = crypto_get_driver_session(cses); | ses = crypto_get_driver_session(cses); | ||||
authini = NULL; | authini = NULL; | ||||
encini = NULL; | encini = NULL; | ||||
gcm = false; | gcm = false; | ||||
gcm_hash = false; | gcm_hash = false; | ||||
ccm = cbc_hash = false; | |||||
for (; cri != NULL; cri = cri->cri_next) { | for (; cri != NULL; cri = cri->cri_next) { | ||||
switch (cri->cri_alg) { | switch (cri->cri_alg) { | ||||
case CRYPTO_AES_NIST_GCM_16: | case CRYPTO_AES_NIST_GCM_16: | ||||
case CRYPTO_AES_CCM_16: | |||||
if (cri->cri_alg == CRYPTO_AES_NIST_GCM_16) { | |||||
gcm = true; | gcm = true; | ||||
} else if (cri->cri_alg == CRYPTO_AES_CCM_16) { | |||||
ccm = true; | |||||
} | |||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
Not Done Inline ActionsI think this might be clearer as a goto + label. case CRYPTO_AES_CCM_16: ccm = true; goto setencini; case ...GCM...: gcm = true; /* FALLTHROUGH */ ... case CRYPTO_AES_XTS: setencini: ... cem: I think this might be clearer as a goto + label.
```
case CRYPTO_AES_CCM_16:
ccm = true… | |||||
case CRYPTO_AES_CBC: | case CRYPTO_AES_CBC: | ||||
case CRYPTO_AES_ICM: | case CRYPTO_AES_ICM: | ||||
case CRYPTO_AES_XTS: | case CRYPTO_AES_XTS: | ||||
if (!sc->has_aes) | if (!sc->has_aes) | ||||
goto unhandled; | goto unhandled; | ||||
if (encini != NULL) { | if (encini != NULL) { | ||||
CRYPTDEB("encini already set"); | CRYPTDEB("encini already set"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
encini = cri; | encini = cri; | ||||
break; | break; | ||||
case CRYPTO_AES_128_CCM_CBC_MAC: | |||||
case CRYPTO_AES_192_CCM_CBC_MAC: | |||||
case CRYPTO_AES_256_CCM_CBC_MAC: | |||||
if (authini != NULL) { | |||||
CRYPTDEB("authini already set"); | |||||
return (EINVAL); | |||||
} | |||||
cbc_hash = true; | |||||
authini = cri; | |||||
break; | |||||
case CRYPTO_AES_128_NIST_GMAC: | case CRYPTO_AES_128_NIST_GMAC: | ||||
case CRYPTO_AES_192_NIST_GMAC: | case CRYPTO_AES_192_NIST_GMAC: | ||||
case CRYPTO_AES_256_NIST_GMAC: | case CRYPTO_AES_256_NIST_GMAC: | ||||
if (authini != NULL) { | |||||
CRYPTDEB("authini already set"); | |||||
return (EINVAL); | |||||
Done Inline ActionsThis bit was already sort of missing a authini != NULL check like below, and now both do. Not a regression in this change. cem: This bit was already sort of missing a `authini != NULL` check like below, and now both do. | |||||
} | |||||
/* | /* | ||||
* nothing to do here, maybe in the future cache some | * nothing to do here, maybe in the future cache some | ||||
* values for GHASH | * values for GHASH | ||||
*/ | */ | ||||
gcm_hash = true; | gcm_hash = true; | ||||
authini = cri; | |||||
break; | break; | ||||
case CRYPTO_SHA1: | case CRYPTO_SHA1: | ||||
case CRYPTO_SHA1_HMAC: | case CRYPTO_SHA1_HMAC: | ||||
case CRYPTO_SHA2_224: | case CRYPTO_SHA2_224: | ||||
case CRYPTO_SHA2_224_HMAC: | case CRYPTO_SHA2_224_HMAC: | ||||
case CRYPTO_SHA2_256: | case CRYPTO_SHA2_256: | ||||
case CRYPTO_SHA2_256_HMAC: | case CRYPTO_SHA2_256_HMAC: | ||||
if (!sc->has_sha) | if (!sc->has_sha) | ||||
Show All 13 Lines | unhandled: | ||||
if (encini == NULL && authini == NULL) { | if (encini == NULL && authini == NULL) { | ||||
CRYPTDEB("no cipher"); | CRYPTDEB("no cipher"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* | /* | ||||
* GMAC algorithms are only supported with simultaneous GCM. Likewise | * GMAC algorithms are only supported with simultaneous GCM. Likewise | ||||
* GCM is not supported without GMAC. | * GCM is not supported without GMAC. | ||||
*/ | */ | ||||
if (gcm_hash != gcm) | if (gcm_hash != gcm) { | ||||
CRYPTDEB("gcm_hash != gcm"); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | |||||
if (cbc_hash != ccm) { | |||||
Not Done Inline ActionsProbably worth a comment about CCM here, or expanding the GCM comment above. cem: Probably worth a comment about CCM here, or expanding the GCM comment above. | |||||
CRYPTDEB("cbc_hash != ccm"); | |||||
return (EINVAL); | |||||
} | |||||
Not Done Inline ActionsIt isn't totally clear, but the encini check plus these equality checks should be sufficient to prove that gcm && ccm is false. I'd add an assertion making that clear: KASSERT((gcm && ccm) ==false, ...); cem: It isn't totally clear, but the `encini` check plus these equality checks should be sufficient… | |||||
if (encini != NULL) | if (encini != NULL) | ||||
ses->algo = encini->cri_alg; | ses->algo = encini->cri_alg; | ||||
if (authini != NULL) | if (authini != NULL) | ||||
ses->auth_algo = authini->cri_alg; | ses->auth_algo = authini->cri_alg; | ||||
error = aesni_cipher_setup(ses, encini, authini); | error = aesni_cipher_setup(ses, encini, authini); | ||||
if (error != 0) { | if (error != 0) { | ||||
CRYPTDEB("setup failed"); | CRYPTDEB("setup failed"); | ||||
Show All 24 Lines | if (crp->crp_callback == NULL || crp->crp_desc == NULL || | ||||
crp->crp_session == NULL) { | crp->crp_session == NULL) { | ||||
error = EINVAL; | error = EINVAL; | ||||
goto out; | goto out; | ||||
} | } | ||||
for (crd = crp->crp_desc; crd != NULL; crd = crd->crd_next) { | for (crd = crp->crp_desc; crd != NULL; crd = crd->crd_next) { | ||||
switch (crd->crd_alg) { | switch (crd->crd_alg) { | ||||
case CRYPTO_AES_NIST_GCM_16: | case CRYPTO_AES_NIST_GCM_16: | ||||
case CRYPTO_AES_CCM_16: | |||||
needauth = 1; | needauth = 1; | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
case CRYPTO_AES_CBC: | case CRYPTO_AES_CBC: | ||||
case CRYPTO_AES_ICM: | case CRYPTO_AES_ICM: | ||||
case CRYPTO_AES_XTS: | case CRYPTO_AES_XTS: | ||||
if (enccrd != NULL) { | if (enccrd != NULL) { | ||||
error = EINVAL; | error = EINVAL; | ||||
goto out; | goto out; | ||||
} | } | ||||
enccrd = crd; | enccrd = crd; | ||||
break; | break; | ||||
case CRYPTO_AES_128_NIST_GMAC: | case CRYPTO_AES_128_NIST_GMAC: | ||||
case CRYPTO_AES_192_NIST_GMAC: | case CRYPTO_AES_192_NIST_GMAC: | ||||
case CRYPTO_AES_256_NIST_GMAC: | case CRYPTO_AES_256_NIST_GMAC: | ||||
case CRYPTO_AES_128_CCM_CBC_MAC: | |||||
case CRYPTO_AES_192_CCM_CBC_MAC: | |||||
case CRYPTO_AES_256_CCM_CBC_MAC: | |||||
case CRYPTO_SHA1: | case CRYPTO_SHA1: | ||||
case CRYPTO_SHA1_HMAC: | case CRYPTO_SHA1_HMAC: | ||||
case CRYPTO_SHA2_224: | case CRYPTO_SHA2_224: | ||||
case CRYPTO_SHA2_224_HMAC: | case CRYPTO_SHA2_224_HMAC: | ||||
case CRYPTO_SHA2_256: | case CRYPTO_SHA2_256: | ||||
case CRYPTO_SHA2_256_HMAC: | case CRYPTO_SHA2_256_HMAC: | ||||
if (authcrd != NULL) { | if (authcrd != NULL) { | ||||
error = EINVAL; | error = EINVAL; | ||||
Show All 30 Lines | if (error != 0) | ||||
goto out; | goto out; | ||||
out: | out: | ||||
crp->crp_etype = error; | crp->crp_etype = error; | ||||
crypto_done(crp); | crypto_done(crp); | ||||
return (error); | return (error); | ||||
} | } | ||||
static uint8_t * | static uint8_t * | ||||
Done Inline ActionsThis particular optimization should probably be a separate commit from adding AES-CCM. jhb: This particular optimization should probably be a separate commit from adding AES-CCM. | |||||
Done Inline ActionsI'd sent that in via email, but never made a differential for it. I can probably do that. It's included here because the ZFS crypto performance without it is simply untenable. sef: I'd sent that in via email, but never made a differential for it. I can probably do that. | |||||
Done Inline ActionsI don't think this optimization is specific to aesni — it's probably something that belongs with generic OCF code, at least. (It could also be done in ZFS instead — constructing single-iov uio's to sent to OCF — but it is a reasonable optimization for OCF to have given it acts on uio objects.) I agree it should be separated from this revision. cem: I don't think this optimization is specific to aesni — it's probably something that belongs… | |||||
aesni_cipher_alloc(struct cryptodesc *enccrd, struct cryptop *crp, | aesni_cipher_alloc(struct cryptodesc *enccrd, struct cryptop *crp, | ||||
bool *allocated) | bool *allocated) | ||||
{ | { | ||||
uint8_t *addr; | uint8_t *addr; | ||||
addr = crypto_contiguous_subsegment(crp->crp_flags, | addr = crypto_contiguous_subsegment(crp->crp_flags, | ||||
Done Inline ActionsThis could be restructured slightly, I think.
That would maybe make it cleaner to apply basically the same optimization to mbuf chains. Anyway, it's mostly fine as-is, except 0 should be false. cem: This could be restructured slightly, I think.
1. Add a stack variable `addr_offset` and… | |||||
crp->crp_buf, enccrd->crd_skip, enccrd->crd_len); | crp->crp_buf, enccrd->crd_skip, enccrd->crd_len); | ||||
if (addr != NULL) { | if (addr != NULL) { | ||||
*allocated = false; | *allocated = false; | ||||
return (addr); | return (addr); | ||||
} | } | ||||
addr = malloc(enccrd->crd_len, M_AESNI, M_NOWAIT); | addr = malloc(enccrd->crd_len, M_AESNI, M_NOWAIT); | ||||
if (addr != NULL) { | if (addr != NULL) { | ||||
*allocated = true; | *allocated = true; | ||||
▲ Show 20 Lines • Show All 225 Lines • ▼ Show 20 Lines | aesni_cipher_process(struct aesni_session *ses, struct cryptodesc *enccrd, | ||||
struct cryptodesc *authcrd, struct cryptop *crp) | struct cryptodesc *authcrd, struct cryptop *crp) | ||||
{ | { | ||||
struct fpu_kern_ctx *ctx; | struct fpu_kern_ctx *ctx; | ||||
int error, ctxidx; | int error, ctxidx; | ||||
bool kt; | bool kt; | ||||
if (enccrd != NULL) { | if (enccrd != NULL) { | ||||
if ((enccrd->crd_alg == CRYPTO_AES_ICM || | if ((enccrd->crd_alg == CRYPTO_AES_ICM || | ||||
enccrd->crd_alg == CRYPTO_AES_CCM_16 || | |||||
enccrd->crd_alg == CRYPTO_AES_NIST_GCM_16) && | enccrd->crd_alg == CRYPTO_AES_NIST_GCM_16) && | ||||
(enccrd->crd_flags & CRD_F_IV_EXPLICIT) == 0) | (enccrd->crd_flags & CRD_F_IV_EXPLICIT) == 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
ctx = NULL; | ctx = NULL; | ||||
ctxidx = 0; | ctxidx = 0; | ||||
error = 0; | error = 0; | ||||
Show All 33 Lines | out: | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
aesni_cipher_crypt(struct aesni_session *ses, struct cryptodesc *enccrd, | aesni_cipher_crypt(struct aesni_session *ses, struct cryptodesc *enccrd, | ||||
struct cryptodesc *authcrd, struct cryptop *crp) | struct cryptodesc *authcrd, struct cryptop *crp) | ||||
{ | { | ||||
uint8_t iv[AES_BLOCK_LEN], tag[GMAC_DIGEST_LEN], *buf, *authbuf; | uint8_t iv[AES_BLOCK_LEN], tag[GMAC_DIGEST_LEN], *buf, *authbuf; | ||||
Not Done Inline ActionsI'd suggest either using MAX() here, or a CTASSERT that GMAC_DIGEST_LEN matches CCM's MAC. cem: I'd suggest either using `MAX()` here, or a CTASSERT that GMAC_DIGEST_LEN matches CCM's MAC. | |||||
int error, ivlen; | int error, ivlen; | ||||
bool encflag, allocated, authallocated; | bool encflag, allocated, authallocated; | ||||
KASSERT(ses->algo != CRYPTO_AES_NIST_GCM_16 || authcrd != NULL, | KASSERT((ses->algo != CRYPTO_AES_NIST_GCM_16 && | ||||
("AES_NIST_GCM_16 must include MAC descriptor")); | ses->algo != CRYPTO_AES_CCM_16) || authcrd != NULL, | ||||
("AES_NIST_GCM_16/AES_CCM_16 must include MAC descriptor")); | |||||
Done Inline ActionsI think this is already well-covered by aesni_cipher_process (which is why it's an assert, not an EINVAL return, I guess) but I'm not sure we need to keep it. If we do keep it, please remove the second space added in the assertion text. cem: I think this is already well-covered by `aesni_cipher_process` (which is why it's an assert… | |||||
ivlen = 0; | ivlen = 0; | ||||
authbuf = NULL; | authbuf = NULL; | ||||
buf = aesni_cipher_alloc(enccrd, crp, &allocated); | buf = aesni_cipher_alloc(enccrd, crp, &allocated); | ||||
if (buf == NULL) | if (buf == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
authallocated = false; | authallocated = false; | ||||
if (ses->algo == CRYPTO_AES_NIST_GCM_16) { | if (ses->algo == CRYPTO_AES_NIST_GCM_16 || | ||||
ses->algo == CRYPTO_AES_CCM_16) { | |||||
authbuf = aesni_cipher_alloc(authcrd, crp, &authallocated); | authbuf = aesni_cipher_alloc(authcrd, crp, &authallocated); | ||||
if (authbuf == NULL) { | if (authbuf == NULL) { | ||||
error = ENOMEM; | error = ENOMEM; | ||||
goto out; | goto out; | ||||
} | } | ||||
} | } | ||||
error = 0; | error = 0; | ||||
Show All 9 Lines | aesni_cipher_crypt(struct aesni_session *ses, struct cryptodesc *enccrd, | ||||
case CRYPTO_AES_CBC: | case CRYPTO_AES_CBC: | ||||
case CRYPTO_AES_ICM: | case CRYPTO_AES_ICM: | ||||
ivlen = AES_BLOCK_LEN; | ivlen = AES_BLOCK_LEN; | ||||
break; | break; | ||||
case CRYPTO_AES_XTS: | case CRYPTO_AES_XTS: | ||||
ivlen = 8; | ivlen = 8; | ||||
break; | break; | ||||
case CRYPTO_AES_NIST_GCM_16: | case CRYPTO_AES_NIST_GCM_16: | ||||
case CRYPTO_AES_CCM_16: | |||||
ivlen = 12; /* should support arbitarily larger */ | ivlen = 12; /* should support arbitarily larger */ | ||||
break; | break; | ||||
} | } | ||||
/* Setup iv */ | /* Setup iv */ | ||||
if (encflag) { | if (encflag) { | ||||
if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0) | if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0) | ||||
bcopy(enccrd->crd_iv, iv, ivlen); | bcopy(enccrd->crd_iv, iv, ivlen); | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | if (encflag) { | ||||
authcrd->crd_inject, GMAC_DIGEST_LEN, tag); | authcrd->crd_inject, GMAC_DIGEST_LEN, tag); | ||||
} else { | } else { | ||||
if (!AES_GCM_decrypt(buf, buf, authbuf, iv, tag, | if (!AES_GCM_decrypt(buf, buf, authbuf, iv, tag, | ||||
enccrd->crd_len, authcrd->crd_len, ivlen, | enccrd->crd_len, authcrd->crd_len, ivlen, | ||||
ses->enc_schedule, ses->rounds)) | ses->enc_schedule, ses->rounds)) | ||||
error = EBADMSG; | error = EBADMSG; | ||||
} | } | ||||
break; | break; | ||||
case CRYPTO_AES_CCM_16: | |||||
if (encflag) { | |||||
bzero(tag, sizeof tag); | |||||
AES_CCM_encrypt(buf, buf, authbuf, iv, tag, | |||||
Not Done Inline ActionsProbably GMAC_DIGEST_LEN is an inappropriate name for a CCM CBC-MAC digest, even if it happens to be the same length. cem: Probably `GMAC_DIGEST_LEN` is an inappropriate name for a CCM CBC-MAC digest, even if it… | |||||
Not Done Inline Actionsso CCM_CBCMAC_DIGEST_LEN? mmacy: so `CCM_CBCMAC_DIGEST_LEN`? | |||||
enccrd->crd_len, authcrd->crd_len, ivlen, | |||||
ses->enc_schedule, ses->rounds); | |||||
if (authcrd != NULL) | |||||
Done Inline ActionsIt seems odd to use exactly the same condition for both of these, with opposite sense. It also seems odd not to reduce it to a single if-else statement. cem: It seems odd to use exactly the same condition for both of these, with opposite sense. It also… | |||||
crypto_copyback(crp->crp_flags, crp->crp_buf, | |||||
authcrd->crd_inject, CCM_CBC_MAX_DIGEST_LEN, tag); | |||||
} else { | |||||
crypto_copydata(crp->crp_flags, crp->crp_buf, | |||||
authcrd->crd_inject, CCM_CBC_MAX_DIGEST_LEN, tag); | |||||
if (!AES_CCM_decrypt(buf, buf, authbuf, iv, tag, | |||||
enccrd->crd_len, authcrd->crd_len, ivlen, | |||||
ses->enc_schedule, ses->rounds)) | |||||
error = EBADMSG; | |||||
} | } | ||||
break; | |||||
if (allocated) | } | ||||
if (allocated && error == 0) | |||||
crypto_copyback(crp->crp_flags, crp->crp_buf, enccrd->crd_skip, | crypto_copyback(crp->crp_flags, crp->crp_buf, enccrd->crd_skip, | ||||
enccrd->crd_len, buf); | enccrd->crd_len, buf); | ||||
out: | out: | ||||
if (allocated) { | if (allocated) { | ||||
explicit_bzero(buf, enccrd->crd_len); | explicit_bzero(buf, enccrd->crd_len); | ||||
free(buf, M_AESNI); | free(buf, M_AESNI); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 102 Lines • Show Last 20 Lines |
I would suggest alpha ordering here too, although XTS is out of place already. The rest are in-place, though.