From b42ac57f4f2c183fda94189f1516ae3c1eff851f Mon Sep 17 00:00:00 2001 From: Hajimu UMEMOTO Date: Mon, 13 Oct 2003 14:57:41 +0000 Subject: [PATCH] - support AES counter mode for ESP. - use size_t as return type of schedlen(), as there's no error check needed. - clear key schedule buffer before freeing. Obtained from: KAME --- lib/libipsec/pfkey_dump.c | 3 + sbin/setkey/setkey.8 | 5 + sbin/setkey/token.l | 1 + share/doc/IPv6/IMPLEMENTATION | 7 +- sys/conf/files | 1 + sys/net/pfkeyv2.h | 8 +- sys/netinet6/esp.h | 2 +- sys/netinet6/esp_aesctr.c | 463 ++++++++++++++++++++++++++++++++++ sys/netinet6/esp_aesctr.h | 42 +++ sys/netinet6/esp_core.c | 30 ++- sys/netinet6/esp_rijndael.c | 2 +- sys/netinet6/esp_rijndael.h | 2 +- usr.sbin/setkey/setkey.8 | 5 + usr.sbin/setkey/token.l | 1 + 14 files changed, 550 insertions(+), 22 deletions(-) create mode 100644 sys/netinet6/esp_aesctr.c create mode 100644 sys/netinet6/esp_aesctr.h diff --git a/lib/libipsec/pfkey_dump.c b/lib/libipsec/pfkey_dump.c index b2cddf2bac2c..0113e141d32e 100644 --- a/lib/libipsec/pfkey_dump.c +++ b/lib/libipsec/pfkey_dump.c @@ -196,6 +196,9 @@ static struct val2str str_alg_enc[] = { #endif #ifdef SADB_X_EALG_TWOFISHCBC { SADB_X_EALG_TWOFISHCBC, "twofish-cbc", }, +#endif +#ifdef SADB_X_EALG_AESCTR + { SADB_X_EALG_AESCTR, "aes-ctr", }, #endif { -1, NULL, }, }; diff --git a/sbin/setkey/setkey.8 b/sbin/setkey/setkey.8 index 680803b08688..4ab8927602a0 100644 --- a/sbin/setkey/setkey.8 +++ b/sbin/setkey/setkey.8 @@ -573,8 +573,13 @@ cast128-cbc 40 to 128 rfc2451 des-deriv 64 ipsec-ciph-des-derived-01 (expired) 3des-deriv 192 no document rijndael-cbc 128/192/256 draft-ietf-ipsec-ciph-aes-cbc-00 +aes-ctr 160/224/288 draft-ietf-ipsec-ciph-aes-ctr-03 .Ed .Pp +Note that the first 128 bits of a key for +.Li aes-ctr +will be used as AES key, and remaining 32 bits will be used as nonce. +.Pp Followings are the list of compression algorithms that can be used as .Ar calgo in diff --git a/sbin/setkey/token.l b/sbin/setkey/token.l index 312df4c3fbd3..5f73594d0155 100644 --- a/sbin/setkey/token.l +++ b/sbin/setkey/token.l @@ -184,6 +184,7 @@ cast128-cbc { PREPROC; yylval.num = SADB_X_EALG_CAST128CBC; return(ALG_ENC); } des-deriv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DESDERIV); } des-32iv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DES32IV); } rijndael-cbc { PREPROC; yylval.num = SADB_X_EALG_RIJNDAELCBC; return(ALG_ENC); } +aes-ctr { PREPROC; yylval.num = SADB_X_EALG_AESCTR; return(ALG_ENC); } /* compression algorithms */ {hyphen}C { PREPROC; return(F_COMP); } diff --git a/share/doc/IPv6/IMPLEMENTATION b/share/doc/IPv6/IMPLEMENTATION index 5bc6bd6d0bc1..50ca51663b81 100644 --- a/share/doc/IPv6/IMPLEMENTATION +++ b/share/doc/IPv6/IMPLEMENTATION @@ -1731,6 +1731,7 @@ Currently supported algorithms are: HMAC SHA2-384 with 96bit crypto checksum (no document) HMAC SHA2-512 with 96bit crypto checksum (no document) HMAC RIPEMD160 with 96bit crypto checksum (RFC2857) + AES XCBC MAC with 96bit crypto checksum (RFC3566) new IPsec ESP null encryption (rfc2410.txt) DES-CBC with derived IV @@ -1739,9 +1740,9 @@ Currently supported algorithms are: 3DES-CBC with explicit IV (rfc2451.txt) BLOWFISH CBC (rfc2451.txt) CAST128 CBC (rfc2451.txt) - RIJNDAEL/AES CBC (draft-ietf-ipsec-ciph-aes-cbc-00.txt, - uses IANA-assigned protocol number) - TWOFISH CBC (draft-ietf-ipsec-ciph-aes-cbc-00.txt) + RIJNDAEL/AES CBC (rfc3602.txt) + AES counter mode (draft-ietf-ipsec-ciph-aes-ctr-03.txt) + each of the above can be combined with: ESP authentication with HMAC-MD5(96bit) ESP authentication with HMAC-SHA1(96bit) diff --git a/sys/conf/files b/sys/conf/files index 84a88f5d45bf..9ba820ae07a3 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1441,6 +1441,7 @@ netinet6/ah_core.c optional ipsec netinet6/ah_input.c optional ipsec netinet6/ah_output.c optional ipsec netinet6/dest6.c optional inet6 +netinet6/esp_aesctr.c optional ipsec ipsec_esp netinet6/esp_core.c optional ipsec ipsec_esp netinet6/esp_input.c optional ipsec ipsec_esp netinet6/esp_output.c optional ipsec ipsec_esp diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h index 6fa8a2d3e945..c0897e5db2d7 100644 --- a/sys/net/pfkeyv2.h +++ b/sys/net/pfkeyv2.h @@ -319,22 +319,22 @@ struct sadb_x_ipsecrequest { #define SADB_EALG_DESCBC 2 #define SADB_EALG_3DESCBC 3 #define SADB_EALG_NULL 11 -#define SADB_EALG_MAX 12 +#define SADB_EALG_MAX 250 /* private allocations - based on RFC2407/IANA assignment */ #define SADB_X_EALG_CAST128CBC 6 #define SADB_X_EALG_BLOWFISHCBC 7 #define SADB_X_EALG_RIJNDAELCBC 12 #define SADB_X_EALG_AES 12 /* private allocations should use 249-255 (RFC2407) */ -#define SADB_X_EALG_SKIPJACK 249 +#define SADB_X_EALG_SKIPJACK 249 /*250*/ /* for FAST_IPSEC */ +#define SADB_X_EALG_AESCTR 250 /*249*/ /* draft-ietf-ipsec-ciph-aes-ctr-03 */ -#if 1 /*nonstandard */ +/* private allocations - based on RFC2407/IANA assignment */ #define SADB_X_CALG_NONE 0 #define SADB_X_CALG_OUI 1 #define SADB_X_CALG_DEFLATE 2 #define SADB_X_CALG_LZS 3 #define SADB_X_CALG_MAX 4 -#endif #define SADB_IDENTTYPE_RESERVED 0 #define SADB_IDENTTYPE_PREFIX 1 diff --git a/sys/netinet6/esp.h b/sys/netinet6/esp.h index 28fe4568706a..ba6c7ae0c67c 100644 --- a/sys/netinet6/esp.h +++ b/sys/netinet6/esp.h @@ -78,7 +78,7 @@ struct esp_algorithm { int (*mature) __P((struct secasvar *)); int keymin; /* in bits */ int keymax; /* in bits */ - int (*schedlen) __P((const struct esp_algorithm *)); + size_t (*schedlen) __P((const struct esp_algorithm *)); const char *name; int (*ivlen) __P((const struct esp_algorithm *, struct secasvar *)); int (*decrypt) __P((struct mbuf *, size_t, diff --git a/sys/netinet6/esp_aesctr.c b/sys/netinet6/esp_aesctr.c new file mode 100644 index 000000000000..9fbd61530a89 --- /dev/null +++ b/sys/netinet6/esp_aesctr.c @@ -0,0 +1,463 @@ +/* $KAME: esp_aesctr.c,v 1.2 2003/07/20 00:29:37 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, 1998 and 2003 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +#include + +#define AES_BLOCKSIZE 16 + +#define NONCESIZE 4 +union cblock { + struct { + u_int8_t nonce[4]; + u_int8_t iv[16]; + u_int32_t ctr; + } v __attribute__((__packed__)); + u_int8_t cblock[16]; +}; + +typedef struct { + u_int32_t r_ek[(RIJNDAEL_MAXNR+1)*4]; + int r_nr; /* key-length-dependent number of rounds */ +} aesctr_ctx; + +int +esp_aesctr_mature(sav) + struct secasvar *sav; +{ + int keylen; + const struct esp_algorithm *algo; + + algo = esp_algorithm_lookup(sav->alg_enc); + if (!algo) { + ipseclog((LOG_ERR, + "esp_aeesctr_mature %s: unsupported algorithm.\n", + algo->name)); + return 1; + } + + keylen = sav->key_enc->sadb_key_bits; + if (keylen < algo->keymin || algo->keymax < keylen) { + ipseclog((LOG_ERR, + "esp_aesctr_mature %s: invalid key length %d.\n", + algo->name, sav->key_enc->sadb_key_bits)); + return 1; + } + + /* rijndael key + nonce */ + if (!(keylen == 128 + 32 || keylen == 192 + 32 || keylen == 256 + 32)) { + ipseclog((LOG_ERR, + "esp_aesctr_mature %s: invalid key length %d.\n", + algo->name, keylen)); + return 1; + } + + return 0; +} + +size_t +esp_aesctr_schedlen(algo) + const struct esp_algorithm *algo; +{ + + return sizeof(aesctr_ctx); +} + +int +esp_aesctr_schedule(algo, sav) + const struct esp_algorithm *algo; + struct secasvar *sav; +{ + aesctr_ctx *ctx; + int keylen; + + /* SA key = AES key + nonce */ + keylen = _KEYLEN(sav->key_enc) * 8 - NONCESIZE * 8; + + ctx = (aesctr_ctx *)sav->sched; + if ((ctx->r_nr = rijndaelKeySetupEnc(ctx->r_ek, + (char *)_KEYBUF(sav->key_enc), keylen)) == 0) + return -1; + return 0; +} + +int +esp_aesctr_decrypt(m, off, sav, algo, ivlen) + struct mbuf *m; + size_t off; + struct secasvar *sav; + const struct esp_algorithm *algo; + int ivlen; +{ + struct mbuf *s; + struct mbuf *d, *d0 = NULL, *dp; + int soff, doff; /* offset from the head of chain, to head of this mbuf */ + int sn, dn; /* offset from the head of the mbuf, to meat */ + size_t ivoff, bodyoff; + union cblock cblock; + u_int8_t keystream[AES_BLOCKSIZE], *nonce; + u_int32_t ctr; + u_int8_t *ivp; + u_int8_t sbuf[AES_BLOCKSIZE], *sp, *dst; + struct mbuf *scut; + int scutoff; + int i; + int blocklen; + aesctr_ctx *ctx; + + if (ivlen != sav->ivlen) { + ipseclog((LOG_ERR, "esp_aesctr_decrypt %s: " + "unsupported ivlen %d\n", algo->name, ivlen)); + goto fail; + } + + /* assumes blocklen == padbound */ + blocklen = algo->padbound; + + ivoff = off + sizeof(struct newesp); + bodyoff = off + sizeof(struct newesp) + ivlen; + + /* setup counter block */ + nonce = _KEYBUF(sav->key_enc) + _KEYLEN(sav->key_enc) - NONCESIZE; + bcopy(nonce, cblock.v.nonce, NONCESIZE); + m_copydata(m, ivoff, ivlen, cblock.v.iv); + ctr = 1; + + if (m->m_pkthdr.len < bodyoff) { + ipseclog((LOG_ERR, "esp_aesctr_decrypt %s: bad len %d/%lu\n", + algo->name, m->m_pkthdr.len, (unsigned long)bodyoff)); + goto fail; + } + if ((m->m_pkthdr.len - bodyoff) % blocklen) { + ipseclog((LOG_ERR, "esp_aesctr_decrypt %s: " + "payload length must be multiple of %d\n", + algo->name, blocklen)); + goto fail; + } + + s = m; + d = d0 = dp = NULL; + soff = doff = sn = dn = 0; + ivp = sp = NULL; + + /* skip bodyoff */ + while (soff < bodyoff) { + if (soff + s->m_len > bodyoff) { + sn = bodyoff - soff; + break; + } + + soff += s->m_len; + s = s->m_next; + } + scut = s; + scutoff = sn; + + /* skip over empty mbuf */ + while (s && s->m_len == 0) + s = s->m_next; + + while (soff < m->m_pkthdr.len) { + /* source */ + if (sn + blocklen <= s->m_len) { + /* body is continuous */ + sp = mtod(s, u_int8_t *) + sn; + } else { + /* body is non-continuous */ + m_copydata(s, sn, blocklen, (caddr_t)sbuf); + sp = sbuf; + } + + /* destination */ + if (!d || dn + blocklen > d->m_len) { + if (d) + dp = d; + MGET(d, M_DONTWAIT, MT_DATA); + i = m->m_pkthdr.len - (soff + sn); + if (d && i > MLEN) { + MCLGET(d, M_DONTWAIT); + if ((d->m_flags & M_EXT) == 0) { + m_free(d); + d = NULL; + } + } + if (!d) { + goto nomem; + } + if (!d0) + d0 = d; + if (dp) + dp->m_next = d; + d->m_len = 0; + d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen; + if (d->m_len > i) + d->m_len = i; + dn = 0; + } + + /* put counter into counter block */ + cblock.v.ctr = htonl(ctr); + + /* setup keystream */ + ctx = (aesctr_ctx *)sav->sched; + rijndaelEncrypt(ctx->r_ek, ctx->r_nr, cblock.cblock, keystream); + + bcopy(sp, mtod(d, u_int8_t *) + dn, blocklen); + dst = mtod(d, u_int8_t *) + dn; + for (i = 0; i < blocklen; i++) + dst[i] ^= keystream[i]; + + ctr++; + + sn += blocklen; + dn += blocklen; + + /* find the next source block */ + while (s && sn >= s->m_len) { + sn -= s->m_len; + soff += s->m_len; + s = s->m_next; + } + + /* skip over empty mbuf */ + while (s && s->m_len == 0) + s = s->m_next; + } + + m_freem(scut->m_next); + scut->m_len = scutoff; + scut->m_next = d0; + + /* just in case */ + bzero(&cblock, sizeof(cblock)); + bzero(keystream, sizeof(keystream)); + + return 0; + +fail: + m_freem(m); + if (d0) + m_freem(d0); + return EINVAL; + +nomem: + m_freem(m); + if (d0) + m_freem(d0); + return ENOBUFS; +} + +int +esp_aesctr_encrypt(m, off, plen, sav, algo, ivlen) + struct mbuf *m; + size_t off; + size_t plen; + struct secasvar *sav; + const struct esp_algorithm *algo; + int ivlen; +{ + struct mbuf *s; + struct mbuf *d, *d0, *dp; + int soff, doff; /* offset from the head of chain, to head of this mbuf */ + int sn, dn; /* offset from the head of the mbuf, to meat */ + size_t ivoff, bodyoff; + union cblock cblock; + u_int8_t keystream[AES_BLOCKSIZE], *nonce; + u_int32_t ctr; + u_int8_t sbuf[AES_BLOCKSIZE], *sp, *dst; + struct mbuf *scut; + int scutoff; + int i; + int blocklen; + aesctr_ctx *ctx; + + if (ivlen != sav->ivlen) { + ipseclog((LOG_ERR, "esp_aesctr_encrypt %s: " + "unsupported ivlen %d\n", algo->name, ivlen)); + m_freem(m); + return EINVAL; + } + + /* assumes blocklen == padbound */ + blocklen = algo->padbound; + + ivoff = off + sizeof(struct newesp); + bodyoff = off + sizeof(struct newesp) + ivlen; + + /* put iv into the packet. */ + /* maybe it is better to overwrite dest, not source */ + m_copyback(m, ivoff, ivlen, sav->iv); + + /* setup counter block */ + nonce = _KEYBUF(sav->key_enc) + _KEYLEN(sav->key_enc) - NONCESIZE; + bcopy(nonce, cblock.v.nonce, NONCESIZE); + m_copydata(m, ivoff, ivlen, cblock.v.iv); + ctr = 1; + + if (m->m_pkthdr.len < bodyoff) { + ipseclog((LOG_ERR, "esp_aesctr_encrypt %s: bad len %d/%lu\n", + algo->name, m->m_pkthdr.len, (unsigned long)bodyoff)); + m_freem(m); + return EINVAL; + } + if ((m->m_pkthdr.len - bodyoff) % blocklen) { + ipseclog((LOG_ERR, "esp_aesctr_encrypt %s: " + "payload length must be multiple of %lu\n", + algo->name, (unsigned long)algo->padbound)); + m_freem(m); + return EINVAL; + } + + s = m; + d = d0 = dp = NULL; + soff = doff = sn = dn = 0; + sp = NULL; + + /* skip bodyoff */ + while (soff < bodyoff) { + if (soff + s->m_len > bodyoff) { + sn = bodyoff - soff; + break; + } + + soff += s->m_len; + s = s->m_next; + } + scut = s; + scutoff = sn; + + /* skip over empty mbuf */ + while (s && s->m_len == 0) + s = s->m_next; + + while (soff < m->m_pkthdr.len) { + /* source */ + if (sn + blocklen <= s->m_len) { + /* body is continuous */ + sp = mtod(s, u_int8_t *) + sn; + } else { + /* body is non-continuous */ + m_copydata(s, sn, blocklen, (caddr_t)sbuf); + sp = sbuf; + } + + /* destination */ + if (!d || dn + blocklen > d->m_len) { + if (d) + dp = d; + MGET(d, M_DONTWAIT, MT_DATA); + i = m->m_pkthdr.len - (soff + sn); + if (d && i > MLEN) { + MCLGET(d, M_DONTWAIT); + if ((d->m_flags & M_EXT) == 0) { + m_free(d); + d = NULL; + } + } + if (!d) { + m_freem(m); + if (d0) + m_freem(d0); + return ENOBUFS; + } + if (!d0) + d0 = d; + if (dp) + dp->m_next = d; + d->m_len = 0; + d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen; + if (d->m_len > i) + d->m_len = i; + dn = 0; + } + + /* put counter into counter block */ + cblock.v.ctr = htonl(ctr); + + /* setup keystream */ + ctx = (aesctr_ctx *)sav->sched; + rijndaelEncrypt(ctx->r_ek, ctx->r_nr, cblock.cblock, keystream); + + bcopy(sp, mtod(d, u_int8_t *) + dn, blocklen); + dst = mtod(d, u_int8_t *) + dn; + for (i = 0; i < blocklen; i++) + dst[i] ^= keystream[i]; + + ctr++; + + sn += blocklen; + dn += blocklen; + + /* find the next source block */ + while (s && sn >= s->m_len) { + sn -= s->m_len; + soff += s->m_len; + s = s->m_next; + } + + /* skip over empty mbuf */ + while (s && s->m_len == 0) + s = s->m_next; + } + + m_freem(scut->m_next); + scut->m_len = scutoff; + scut->m_next = d0; + + /* just in case */ + bzero(&cblock, sizeof(cblock)); + bzero(keystream, sizeof(keystream)); + + key_sa_stir_iv(sav); + + return 0; +} diff --git a/sys/netinet6/esp_aesctr.h b/sys/netinet6/esp_aesctr.h new file mode 100644 index 000000000000..bb7f7eaf0e4f --- /dev/null +++ b/sys/netinet6/esp_aesctr.h @@ -0,0 +1,42 @@ +/* $KAME: esp_aesctr.h,v 1.2 2003/07/20 00:29:38 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, 1998 and 2003 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +extern int esp_aesctr_mature __P((struct secasvar *)); +extern size_t esp_aesctr_schedlen __P((const struct esp_algorithm *)); +extern int esp_aesctr_schedule __P((const struct esp_algorithm *, + struct secasvar *)); +extern int esp_aesctr_decrypt __P((struct mbuf *, size_t, + struct secasvar *, const struct esp_algorithm *, int)); +extern int esp_aesctr_encrypt __P((struct mbuf *, size_t, size_t, + struct secasvar *, const struct esp_algorithm *, int)); + diff --git a/sys/netinet6/esp_core.c b/sys/netinet6/esp_core.c index 148d9c42f96f..bfb0713a22c7 100644 --- a/sys/netinet6/esp_core.c +++ b/sys/netinet6/esp_core.c @@ -68,9 +68,11 @@ #include #endif #include +#include #include #include #include + #include #include #include @@ -87,7 +89,7 @@ static int esp_descbc_ivlen __P((const struct esp_algorithm *, struct secasvar *)); static int esp_des_schedule __P((const struct esp_algorithm *, struct secasvar *)); -static int esp_des_schedlen __P((const struct esp_algorithm *)); +static size_t esp_des_schedlen __P((const struct esp_algorithm *)); static int esp_des_blockdecrypt __P((const struct esp_algorithm *, struct secasvar *, u_int8_t *, u_int8_t *)); static int esp_des_blockencrypt __P((const struct esp_algorithm *, @@ -95,21 +97,21 @@ static int esp_des_blockencrypt __P((const struct esp_algorithm *, static int esp_cbc_mature __P((struct secasvar *)); static int esp_blowfish_schedule __P((const struct esp_algorithm *, struct secasvar *)); -static int esp_blowfish_schedlen __P((const struct esp_algorithm *)); +static size_t esp_blowfish_schedlen __P((const struct esp_algorithm *)); static int esp_blowfish_blockdecrypt __P((const struct esp_algorithm *, struct secasvar *, u_int8_t *, u_int8_t *)); static int esp_blowfish_blockencrypt __P((const struct esp_algorithm *, struct secasvar *, u_int8_t *, u_int8_t *)); static int esp_cast128_schedule __P((const struct esp_algorithm *, struct secasvar *)); -static int esp_cast128_schedlen __P((const struct esp_algorithm *)); +static size_t esp_cast128_schedlen __P((const struct esp_algorithm *)); static int esp_cast128_blockdecrypt __P((const struct esp_algorithm *, struct secasvar *, u_int8_t *, u_int8_t *)); static int esp_cast128_blockencrypt __P((const struct esp_algorithm *, struct secasvar *, u_int8_t *, u_int8_t *)); static int esp_3des_schedule __P((const struct esp_algorithm *, struct secasvar *)); -static int esp_3des_schedlen __P((const struct esp_algorithm *)); +static size_t esp_3des_schedlen __P((const struct esp_algorithm *)); static int esp_3des_blockdecrypt __P((const struct esp_algorithm *, struct secasvar *, u_int8_t *, u_int8_t *)); static int esp_3des_blockencrypt __P((const struct esp_algorithm *, @@ -134,7 +136,7 @@ static const struct esp_algorithm esp_algorithms[] = { esp_common_ivlen, esp_cbc_decrypt, esp_cbc_encrypt, esp_3des_schedule, esp_3des_blockdecrypt, esp_3des_blockencrypt, }, - { 1, 0, esp_null_mature, 0, 2048, 0, "null", + { 1, 0, esp_null_mature, 0, 2048, NULL, "null", esp_common_ivlen, esp_null_decrypt, esp_null_encrypt, NULL, }, { 8, 8, esp_cbc_mature, 40, 448, esp_blowfish_schedlen, "blowfish-cbc", @@ -151,6 +153,9 @@ static const struct esp_algorithm esp_algorithms[] = { esp_common_ivlen, esp_cbc_decrypt, esp_cbc_encrypt, esp_rijndael_schedule, esp_rijndael_blockdecrypt, esp_rijndael_blockencrypt }, + { 16, 8, esp_aesctr_mature, 160, 288, esp_aesctr_schedlen, "aes-ctr", + esp_common_ivlen, esp_aesctr_decrypt, + esp_aesctr_encrypt, esp_aesctr_schedule }, }; const struct esp_algorithm * @@ -171,6 +176,8 @@ esp_algorithm_lookup(idx) return &esp_algorithms[4]; case SADB_X_EALG_RIJNDAELCBC: return &esp_algorithms[5]; + case SADB_X_EALG_AESCTR: + return &esp_algorithms[6]; default: return NULL; } @@ -216,8 +223,6 @@ esp_schedule(algo, sav) return 0; sav->schedlen = (*algo->schedlen)(algo); - if (sav->schedlen < 0) - return EINVAL; sav->sched = malloc(sav->schedlen, M_SECA, M_NOWAIT); if (!sav->sched) { sav->schedlen = 0; @@ -228,6 +233,7 @@ esp_schedule(algo, sav) if (error) { ipseclog((LOG_ERR, "esp_schedule %s: error %d\n", algo->name, error)); + bzero(sav->sched, sav->schedlen); free(sav->sched, M_SECA); sav->sched = NULL; sav->schedlen = 0; @@ -326,7 +332,7 @@ esp_descbc_ivlen(algo, sav) return 8; } -static int +static size_t esp_des_schedlen(algo) const struct esp_algorithm *algo; { @@ -443,7 +449,7 @@ esp_cbc_mature(sav) return 0; } -static int +static size_t esp_blowfish_schedlen(algo) const struct esp_algorithm *algo; { @@ -502,12 +508,12 @@ esp_blowfish_blockencrypt(algo, sav, s, d) return 0; } -static int +static size_t esp_cast128_schedlen(algo) const struct esp_algorithm *algo; { - return sizeof(u_int32_t) * 32; + return sizeof(cast128_key); } static int @@ -545,7 +551,7 @@ esp_cast128_blockencrypt(algo, sav, s, d) return 0; } -static int +static size_t esp_3des_schedlen(algo) const struct esp_algorithm *algo; { diff --git a/sys/netinet6/esp_rijndael.c b/sys/netinet6/esp_rijndael.c index 950bbe827f85..e8c699587dba 100644 --- a/sys/netinet6/esp_rijndael.c +++ b/sys/netinet6/esp_rijndael.c @@ -51,7 +51,7 @@ #include /* as rijndael uses assymetric scheduled keys, we need to do it twice. */ -int +size_t esp_rijndael_schedlen(algo) const struct esp_algorithm *algo; { diff --git a/sys/netinet6/esp_rijndael.h b/sys/netinet6/esp_rijndael.h index 0c40d78c5363..5018bf11ac5a 100644 --- a/sys/netinet6/esp_rijndael.h +++ b/sys/netinet6/esp_rijndael.h @@ -30,7 +30,7 @@ * SUCH DAMAGE. */ -int esp_rijndael_schedlen __P((const struct esp_algorithm *)); +size_t esp_rijndael_schedlen __P((const struct esp_algorithm *)); int esp_rijndael_schedule __P((const struct esp_algorithm *, struct secasvar *)); int esp_rijndael_blockdecrypt __P((const struct esp_algorithm *, diff --git a/usr.sbin/setkey/setkey.8 b/usr.sbin/setkey/setkey.8 index 680803b08688..4ab8927602a0 100644 --- a/usr.sbin/setkey/setkey.8 +++ b/usr.sbin/setkey/setkey.8 @@ -573,8 +573,13 @@ cast128-cbc 40 to 128 rfc2451 des-deriv 64 ipsec-ciph-des-derived-01 (expired) 3des-deriv 192 no document rijndael-cbc 128/192/256 draft-ietf-ipsec-ciph-aes-cbc-00 +aes-ctr 160/224/288 draft-ietf-ipsec-ciph-aes-ctr-03 .Ed .Pp +Note that the first 128 bits of a key for +.Li aes-ctr +will be used as AES key, and remaining 32 bits will be used as nonce. +.Pp Followings are the list of compression algorithms that can be used as .Ar calgo in diff --git a/usr.sbin/setkey/token.l b/usr.sbin/setkey/token.l index 312df4c3fbd3..5f73594d0155 100644 --- a/usr.sbin/setkey/token.l +++ b/usr.sbin/setkey/token.l @@ -184,6 +184,7 @@ cast128-cbc { PREPROC; yylval.num = SADB_X_EALG_CAST128CBC; return(ALG_ENC); } des-deriv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DESDERIV); } des-32iv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DES32IV); } rijndael-cbc { PREPROC; yylval.num = SADB_X_EALG_RIJNDAELCBC; return(ALG_ENC); } +aes-ctr { PREPROC; yylval.num = SADB_X_EALG_AESCTR; return(ALG_ENC); } /* compression algorithms */ {hyphen}C { PREPROC; return(F_COMP); }