Push CBC-MAC and CCM block updates into the aes_impl API.
This should help reduce the setup and teardown overhead (enabling and disabling fpu, or expanding bitsliced keys) for CCM, as used in 802.11 WPA2 CCMP. But all the fiddly formatting details remain in aes_ccm.c to reduce the effort of implementing it -- at the cost of a handful additional setups and teardowns per message. Not yet implemented by any of the aes_impls, so leave a fallback that just calls aes_enc for now. This should be removed when all of the aes_impls provide CBC-MAC and CCM block updates.
This commit is contained in:
parent
c79a1e3b24
commit
ebf44a5b26
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: aes_ccm.c,v 1.1 2020/07/25 22:15:55 riastradh Exp $ */
|
||||
/* $NetBSD: aes_ccm.c,v 1.2 2020/07/25 22:27:53 riastradh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2020 The NetBSD Foundation, Inc.
|
||||
|
@ -35,7 +35,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(1, "$NetBSD: aes_ccm.c,v 1.1 2020/07/25 22:15:55 riastradh Exp $");
|
||||
__KERNEL_RCSID(1, "$NetBSD: aes_ccm.c,v 1.2 2020/07/25 22:27:53 riastradh Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
@ -45,6 +45,7 @@ __KERNEL_RCSID(1, "$NetBSD: aes_ccm.c,v 1.1 2020/07/25 22:15:55 riastradh Exp $"
|
|||
|
||||
#include <crypto/aes/aes.h>
|
||||
#include <crypto/aes/aes_ccm.h>
|
||||
#include <crypto/aes/aes_impl.h>
|
||||
|
||||
static inline void
|
||||
xor(uint8_t *x, const uint8_t *a, const uint8_t *b, size_t n)
|
||||
|
@ -54,13 +55,6 @@ xor(uint8_t *x, const uint8_t *a, const uint8_t *b, size_t n)
|
|||
*x++ = *a++ ^ *b++;
|
||||
}
|
||||
|
||||
static inline void
|
||||
xor16(uint8_t *x, const uint8_t *a, const uint8_t *b)
|
||||
{
|
||||
|
||||
xor(x, a, b, 16);
|
||||
}
|
||||
|
||||
/* RFC 3610, §2.2 Authentication */
|
||||
#define CCM_AFLAGS_ADATA __BIT(6)
|
||||
#define CCM_AFLAGS_M __BITS(5,3)
|
||||
|
@ -157,9 +151,10 @@ aes_ccm_init(struct aes_ccm *C, unsigned nr, const struct aesenc *enc,
|
|||
aes_enc(enc, C->auth, C->auth, C->nr);
|
||||
|
||||
/* If there was anything more, process 16 bytes at a time. */
|
||||
for (; adlen >= 16; adp += 16, adlen -= 16) {
|
||||
xor16(C->auth, C->auth, adp);
|
||||
aes_enc(enc, C->auth, C->auth, C->nr);
|
||||
if (adlen - (adlen % 16)) {
|
||||
aes_cbcmac_update1(enc, adp, adlen - (adlen % 16),
|
||||
C->auth, C->nr);
|
||||
adlen %= 16;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -217,15 +212,12 @@ aes_ccm_enc(struct aes_ccm *C, const void *in, void *out, size_t nbytes)
|
|||
}
|
||||
|
||||
/* Process 16 bytes at a time. */
|
||||
for (; nbytes >= 16; p += 16, q += 16, nbytes -= 16) {
|
||||
/* authenticate */
|
||||
xor16(C->auth, C->auth, p);
|
||||
aes_enc(C->enc, C->auth, C->auth, C->nr);
|
||||
|
||||
/* encrypt */
|
||||
aes_ccm_inc(C);
|
||||
aes_enc(C->enc, C->in, C->out, C->nr);
|
||||
xor16(q, C->out, p);
|
||||
if (nbytes - (nbytes % 16)) {
|
||||
aes_ccm_enc1(C->enc, p, q, nbytes - (nbytes % 16), C->auth,
|
||||
C->nr);
|
||||
p += nbytes - (nbytes % 16);
|
||||
q += nbytes - (nbytes % 16);
|
||||
nbytes %= 16;
|
||||
}
|
||||
|
||||
/* Incorporate any <16-byte unit as a partial block. */
|
||||
|
@ -278,15 +270,12 @@ aes_ccm_dec(struct aes_ccm *C, const void *in, void *out, size_t nbytes)
|
|||
}
|
||||
|
||||
/* Process 16 bytes at a time. */
|
||||
for (; nbytes >= 16; p += 16, q += 16, nbytes -= 16) {
|
||||
/* decrypt */
|
||||
aes_ccm_inc(C);
|
||||
aes_enc(C->enc, C->in, C->out, C->nr);
|
||||
xor16(q, C->out, p);
|
||||
|
||||
/* authenticate */
|
||||
xor16(C->auth, C->auth, q);
|
||||
aes_enc(C->enc, C->auth, C->auth, C->nr);
|
||||
if (nbytes - (nbytes % 16)) {
|
||||
aes_ccm_dec1(C->enc, p, q, nbytes - (nbytes % 16), C->auth,
|
||||
C->nr);
|
||||
p += nbytes - (nbytes % 16);
|
||||
q += nbytes - (nbytes % 16);
|
||||
nbytes %= 16;
|
||||
}
|
||||
|
||||
/* Incorporate any <16-byte unit as a partial block. */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: aes_impl.c,v 1.5 2020/07/25 22:14:35 riastradh Exp $ */
|
||||
/* $NetBSD: aes_impl.c,v 1.6 2020/07/25 22:27:53 riastradh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2020 The NetBSD Foundation, Inc.
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(1, "$NetBSD: aes_impl.c,v 1.5 2020/07/25 22:14:35 riastradh Exp $");
|
||||
__KERNEL_RCSID(1, "$NetBSD: aes_impl.c,v 1.6 2020/07/25 22:27:53 riastradh Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/kernel.h>
|
||||
|
@ -288,6 +288,90 @@ aes_xts_dec(struct aesdec *dec, const uint8_t in[static 16],
|
|||
aes_impl->ai_xts_dec(dec, in, out, nbytes, tweak, nrounds);
|
||||
}
|
||||
|
||||
static void
|
||||
xor16(uint8_t *x, const uint8_t *a, const uint8_t *b)
|
||||
{
|
||||
|
||||
le32enc(x + 4*0, le32dec(a + 4*0) ^ le32dec(b + 4*0));
|
||||
le32enc(x + 4*1, le32dec(a + 4*1) ^ le32dec(b + 4*1));
|
||||
le32enc(x + 4*2, le32dec(a + 4*2) ^ le32dec(b + 4*2));
|
||||
le32enc(x + 4*3, le32dec(a + 4*3) ^ le32dec(b + 4*3));
|
||||
}
|
||||
|
||||
void
|
||||
aes_cbcmac_update1(const struct aesenc *enc, const uint8_t in[static 16],
|
||||
size_t nbytes, uint8_t auth[static 16], uint32_t nrounds)
|
||||
{
|
||||
|
||||
KASSERT(nbytes);
|
||||
KASSERT(nbytes % 16 == 0);
|
||||
|
||||
aes_guarantee_selected();
|
||||
if (aes_impl->ai_cbcmac_update1) {
|
||||
aes_impl->ai_cbcmac_update1(enc, in, nbytes, auth, nrounds);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; nbytes; in += 16, nbytes -= 16) {
|
||||
xor16(auth, auth, in);
|
||||
aes_enc(enc, auth, auth, nrounds);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
aes_ccm_enc1(const struct aesenc *enc, const uint8_t in[static 16],
|
||||
uint8_t out[static 16], size_t nbytes, uint8_t authctr[static 32],
|
||||
uint32_t nrounds)
|
||||
{
|
||||
uint8_t *auth = authctr;
|
||||
uint8_t *ctr = authctr + 16;
|
||||
|
||||
KASSERT(nbytes);
|
||||
KASSERT(nbytes % 16 == 0);
|
||||
|
||||
aes_guarantee_selected();
|
||||
if (aes_impl->ai_ccm_enc1) {
|
||||
aes_impl->ai_ccm_enc1(enc, in, out, nbytes, auth, nrounds);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; nbytes; in += 16, out += 16, nbytes -= 16) {
|
||||
xor16(auth, auth, in);
|
||||
aes_enc(enc, auth, auth, nrounds);
|
||||
|
||||
be32enc(ctr + 12, 1 + be32dec(ctr + 12));
|
||||
aes_enc(enc, ctr, out, nrounds);
|
||||
xor16(out, out, in);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
aes_ccm_dec1(const struct aesenc *enc, const uint8_t in[static 16],
|
||||
uint8_t out[static 16], size_t nbytes, uint8_t authctr[static 32],
|
||||
uint32_t nrounds)
|
||||
{
|
||||
uint8_t *auth = authctr;
|
||||
uint8_t *ctr = authctr + 16;
|
||||
|
||||
KASSERT(nbytes);
|
||||
KASSERT(nbytes % 16 == 0);
|
||||
|
||||
aes_guarantee_selected();
|
||||
if (aes_impl->ai_ccm_dec1) {
|
||||
aes_impl->ai_ccm_dec1(enc, in, out, nbytes, auth, nrounds);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; nbytes >= 16; in += 16, out += 16, nbytes -= 16) {
|
||||
be32enc(ctr + 12, 1 + be32dec(ctr + 12));
|
||||
aes_enc(enc, ctr, out, nrounds);
|
||||
xor16(out, out, in);
|
||||
|
||||
xor16(auth, auth, out);
|
||||
aes_enc(enc, auth, auth, nrounds);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Known-answer self-tests for the standard key schedule.
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: aes_impl.h,v 1.1 2020/07/25 22:12:57 riastradh Exp $ */
|
||||
/* $NetBSD: aes_impl.h,v 1.2 2020/07/25 22:27:53 riastradh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2020 The NetBSD Foundation, Inc.
|
||||
|
@ -51,10 +51,27 @@ struct aes_impl {
|
|||
uint8_t[static 16], size_t, uint8_t[static 16], uint32_t);
|
||||
void (*ai_xts_dec)(const struct aesdec *, const uint8_t[static 16],
|
||||
uint8_t[static 16], size_t, uint8_t[static 16], uint32_t);
|
||||
void (*ai_cbcmac_update1)(const struct aesenc *,
|
||||
const uint8_t[static 16], size_t, uint8_t[static 16],
|
||||
uint32_t);
|
||||
void (*ai_ccm_enc1)(const struct aesenc *,
|
||||
const uint8_t[static 16], uint8_t[static 16],
|
||||
size_t, uint8_t[static 32], uint32_t);
|
||||
void (*ai_ccm_dec1)(const struct aesenc *,
|
||||
const uint8_t[static 16], uint8_t[static 16],
|
||||
size_t, uint8_t[static 32], uint32_t);
|
||||
};
|
||||
|
||||
void aes_md_init(const struct aes_impl *);
|
||||
|
||||
int aes_selftest(const struct aes_impl *);
|
||||
|
||||
/* Internal subroutines dispatched to implementation for AES-CCM. */
|
||||
void aes_cbcmac_update1(const struct aesenc *, const uint8_t[static 16],
|
||||
size_t, uint8_t[static 16], uint32_t);
|
||||
void aes_ccm_enc1(const struct aesenc *, const uint8_t[static 16],
|
||||
uint8_t[static 16], size_t, uint8_t[static 32], uint32_t);
|
||||
void aes_ccm_dec1(const struct aesenc *, const uint8_t[static 16],
|
||||
uint8_t[static 16], size_t, uint8_t[static 32], uint32_t);
|
||||
|
||||
#endif /* _CRYPTO_AES_AES_IMPL_H */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: aes_selftest.c,v 1.3 2020/07/25 22:12:57 riastradh Exp $ */
|
||||
/* $NetBSD: aes_selftest.c,v 1.4 2020/07/25 22:27:53 riastradh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2020 The NetBSD Foundation, Inc.
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(1, "$NetBSD: aes_selftest.c,v 1.3 2020/07/25 22:12:57 riastradh Exp $");
|
||||
__KERNEL_RCSID(1, "$NetBSD: aes_selftest.c,v 1.4 2020/07/25 22:27:53 riastradh Exp $");
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
|
@ -400,6 +400,149 @@ aes_selftest_encdec_xts(const struct aes_impl *impl)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
aes_selftest_cbcmac(const struct aes_impl *impl)
|
||||
{
|
||||
static const uint8_t m[48] = {
|
||||
0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07,
|
||||
0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
|
||||
0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17,
|
||||
0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f,
|
||||
0x20,0x21,0x22,0x23, 0x24,0x25,0x26,0x27,
|
||||
0x28,0x29,0x2a,0x2b, 0x2c,0x2d,0x2e,0x2f,
|
||||
};
|
||||
static uint8_t auth16[16] = {
|
||||
0x7a,0xca,0x0f,0xd9, 0xbc,0xd6,0xec,0x7c,
|
||||
0x9f,0x97,0x46,0x66, 0x16,0xe6,0xa2,0x82,
|
||||
};
|
||||
static uint8_t auth48[16] = {
|
||||
0x26,0x9a,0xe5,0xfc, 0x8c,0x53,0x0f,0xf7,
|
||||
0x6b,0xd9,0xec,0x05, 0x40,0xf7,0x35,0x13,
|
||||
};
|
||||
static const uint8_t key[16];
|
||||
struct aesenc enc;
|
||||
uint8_t auth[16];
|
||||
const unsigned nr = AES_128_NROUNDS;
|
||||
|
||||
if (impl->ai_cbcmac_update1 == NULL)
|
||||
return 0;
|
||||
|
||||
memset(auth, 0, sizeof auth);
|
||||
|
||||
impl->ai_setenckey(&enc, key, nr);
|
||||
impl->ai_cbcmac_update1(&enc, m, 16, auth, nr);
|
||||
if (memcmp(auth, auth16, 16))
|
||||
return aes_selftest_fail(impl, auth, auth16, 16,
|
||||
"AES-128 CBC-MAC (16)");
|
||||
impl->ai_cbcmac_update1(&enc, m + 16, 32, auth, nr);
|
||||
if (memcmp(auth, auth48, 16))
|
||||
return aes_selftest_fail(impl, auth, auth48, 16,
|
||||
"AES-128 CBC-MAC (48)");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
aes_selftest_ccm(const struct aes_impl *impl)
|
||||
{
|
||||
static const uint8_t ptxt[48] = {
|
||||
0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07,
|
||||
0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
|
||||
0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17,
|
||||
0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f,
|
||||
0x20,0x21,0x22,0x23, 0x24,0x25,0x26,0x27,
|
||||
0x28,0x29,0x2a,0x2b, 0x2c,0x2d,0x2e,0x2f,
|
||||
};
|
||||
static uint8_t ctr0[16] = {
|
||||
/* L - 1, #octets in counter */
|
||||
[0] = 0x01,
|
||||
/* nonce */
|
||||
[1] = 0,1,2,3,4,5,6,7,8,9,10,11,12,
|
||||
[14] = 0,
|
||||
[15] = 254,
|
||||
};
|
||||
static uint8_t authctr16[32] = {
|
||||
/* authentication tag */
|
||||
0x7a,0xca,0x0f,0xd9, 0xbc,0xd6,0xec,0x7c,
|
||||
0x9f,0x97,0x46,0x66, 0x16,0xe6,0xa2,0x82,
|
||||
|
||||
/* L - 1, #octets in counter */
|
||||
[16 + 0] = 0x01,
|
||||
/* nonce */
|
||||
[16 + 1] = 0,1,2,3,4,5,6,7,8,9,10,11,12,
|
||||
[16 + 14] = 0,
|
||||
[16 + 15] = 255,
|
||||
};
|
||||
static uint8_t authctr48[32] = {
|
||||
/* authentication tag */
|
||||
0x26,0x9a,0xe5,0xfc, 0x8c,0x53,0x0f,0xf7,
|
||||
0x6b,0xd9,0xec,0x05, 0x40,0xf7,0x35,0x13,
|
||||
|
||||
/* L - 1, #octets in counter */
|
||||
[16 + 0] = 0x01,
|
||||
/* nonce */
|
||||
[16 + 1] = 0,1,2,3,4,5,6,7,8,9,10,11,12,
|
||||
[16 + 14] = 1,
|
||||
[16 + 15] = 1,
|
||||
};
|
||||
static uint8_t ctxt[48] = {
|
||||
0xa4,0x35,0x07,0x5c, 0xdf,0x2d,0x67,0xd3,
|
||||
0xbf,0x1f,0x36,0x93, 0xe4,0x43,0xcb,0x1e,
|
||||
0xa0,0x82,0x9c,0x2a, 0x0b,0x66,0x46,0x05,
|
||||
0x80,0x17,0x71,0xa1, 0x7b,0x09,0xa7,0xd5,
|
||||
0x91,0x0b,0xb3,0x96, 0xd1,0x5e,0x29,0x3e,
|
||||
0x74,0x94,0x74,0x6d, 0x6b,0x25,0x43,0x8c,
|
||||
};
|
||||
static const uint8_t key[16];
|
||||
struct aesenc enc;
|
||||
uint8_t authctr[32];
|
||||
uint8_t buf[48];
|
||||
const unsigned nr = AES_128_NROUNDS;
|
||||
int result = 0;
|
||||
|
||||
if (impl->ai_ccm_enc1 == NULL)
|
||||
return 0;
|
||||
|
||||
impl->ai_setenckey(&enc, key, nr);
|
||||
|
||||
memset(authctr, 0, 16);
|
||||
memcpy(authctr + 16, ctr0, 16);
|
||||
|
||||
impl->ai_ccm_enc1(&enc, ptxt, buf, 16, authctr, nr);
|
||||
if (memcmp(authctr, authctr16, 32))
|
||||
result |= aes_selftest_fail(impl, authctr, authctr16, 32,
|
||||
"AES-128 CCM encrypt auth/ctr (16)");
|
||||
impl->ai_ccm_enc1(&enc, ptxt + 16, buf + 16, 32, authctr, nr);
|
||||
if (memcmp(authctr, authctr48, 32))
|
||||
result |= aes_selftest_fail(impl, authctr, authctr48, 32,
|
||||
"AES-128 CCM encrypt auth/ctr (48)");
|
||||
|
||||
if (memcmp(buf, ctxt, 32))
|
||||
result |= aes_selftest_fail(impl, buf, ctxt, 48,
|
||||
"AES-128 CCM ciphertext");
|
||||
|
||||
if (impl->ai_ccm_dec1 == NULL)
|
||||
return result;
|
||||
|
||||
memset(authctr, 0, 16);
|
||||
memcpy(authctr + 16, ctr0, 16);
|
||||
|
||||
impl->ai_ccm_dec1(&enc, ctxt, buf, 16, authctr, nr);
|
||||
if (memcmp(authctr, authctr16, 32))
|
||||
result |= aes_selftest_fail(impl, authctr, authctr16, 32,
|
||||
"AES-128 CCM decrypt auth/ctr (16)");
|
||||
impl->ai_ccm_dec1(&enc, ctxt + 16, buf + 16, 32, authctr, nr);
|
||||
if (memcmp(authctr, authctr48, 32))
|
||||
result |= aes_selftest_fail(impl, authctr, authctr48, 32,
|
||||
"AES-128 CCM decrypt auth/ctr (48)");
|
||||
|
||||
if (memcmp(buf, ptxt, 32))
|
||||
result |= aes_selftest_fail(impl, buf, ptxt, 48,
|
||||
"AES-128 CCM plaintext");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
aes_selftest(const struct aes_impl *impl)
|
||||
{
|
||||
|
@ -414,6 +557,10 @@ aes_selftest(const struct aes_impl *impl)
|
|||
result = -1;
|
||||
if (aes_selftest_encdec_xts(impl))
|
||||
result = -1;
|
||||
if (aes_selftest_cbcmac(impl))
|
||||
result = -1;
|
||||
if (aes_selftest_ccm(impl))
|
||||
result = -1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue