summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2005-05-25 05:47:54 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2005-05-25 05:47:54 +0000
commit2e172c5c337953c5b261a718c224233f55f766fa (patch)
tree04020363676641299cc1fc4c174c92903fc2557d
parentda59a2318f0f71de02a778d5bfa0e8c13ea567d4 (diff)
AESCTR support for ESP (RFC 3686); ok hshoexer
-rw-r--r--regress/sys/crypto/Makefile4
-rw-r--r--regress/sys/crypto/aesctr/Makefile10
-rw-r--r--regress/sys/crypto/aesctr/aesctr.c300
-rw-r--r--sys/crypto/cryptodev.c5
-rw-r--r--sys/crypto/cryptodev.h5
-rw-r--r--sys/crypto/cryptosoft.c47
-rw-r--r--sys/crypto/rijndael.c4
-rw-r--r--sys/crypto/rijndael.h4
-rw-r--r--sys/crypto/xform.c119
-rw-r--r--sys/crypto/xform.h6
-rw-r--r--sys/net/pfkeyv2.c12
-rw-r--r--sys/net/pfkeyv2.h3
-rw-r--r--sys/net/pfkeyv2_convert.c6
-rw-r--r--sys/netinet/ip_esp.c11
14 files changed, 487 insertions, 49 deletions
diff --git a/regress/sys/crypto/Makefile b/regress/sys/crypto/Makefile
index 7edc911464d..e2a2269aa53 100644
--- a/regress/sys/crypto/Makefile
+++ b/regress/sys/crypto/Makefile
@@ -1,7 +1,7 @@
-# $OpenBSD: Makefile,v 1.3 2004/03/14 18:37:52 markus Exp $
+# $OpenBSD: Makefile,v 1.4 2005/05/25 05:47:53 markus Exp $
SUBDIR=enc
-#SUBDIR+=auth
+SUBDIR+=aesctr
install:
diff --git a/regress/sys/crypto/aesctr/Makefile b/regress/sys/crypto/aesctr/Makefile
new file mode 100644
index 00000000000..31ae500f188
--- /dev/null
+++ b/regress/sys/crypto/aesctr/Makefile
@@ -0,0 +1,10 @@
+# $OpenBSD: Makefile,v 1.1 2005/05/25 05:47:53 markus Exp $
+
+PROG= aesctr
+
+REGRESS_ROOT_TARGETS= run-regress-${PROG}
+
+run-regress-${PROG}: ${PROG}
+ ${SUDO} ./${PROG}
+
+.include <bsd.regress.mk>
diff --git a/regress/sys/crypto/aesctr/aesctr.c b/regress/sys/crypto/aesctr/aesctr.c
new file mode 100644
index 00000000000..4cc1a6e39ce
--- /dev/null
+++ b/regress/sys/crypto/aesctr/aesctr.c
@@ -0,0 +1,300 @@
+/* $OpenBSD: aesctr.c,v 1.1 2005/05/25 05:47:53 markus Exp $ */
+
+/*
+ * Copyright (c) 2005 Markus Friedl <markus@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/sysctl.h>
+#include <crypto/cryptodev.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+
+int debug = 0;
+
+enum { TST_KEY, TST_IV, TST_PLAIN, TST_CIPHER, TST_NUM };
+
+/* Test vectors from RFC 3686 */
+struct {
+ char *data[TST_NUM];
+} tests[] = {
+ /* 128 bit key */
+ {
+ "AE 68 52 F8 12 10 67 CC 4B F7 A5 76 55 77 F3 9E "
+ "00 00 00 30",
+ "00 00 00 00 00 00 00 00",
+ "53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67",
+ "E4 09 5D 4F B7 A7 B3 79 2D 61 75 A3 26 13 11 B8"
+ },
+ {
+ "7E 24 06 78 17 FA E0 D7 43 D6 CE 1F 32 53 91 63 "
+ "00 6C B6 DB",
+ "C0 54 3B 59 DA 48 D9 0B",
+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F "
+ "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F",
+ "51 04 A1 06 16 8A 72 D9 79 0D 41 EE 8E DA D3 88 "
+ "EB 2E 1E FC 46 DA 57 C8 FC E6 30 DF 91 41 BE 28"
+ },
+ {
+ "76 91 BE 03 5E 50 20 A8 AC 6E 61 85 29 F9 A0 DC "
+ "00 E0 01 7B",
+ "27 77 7F 3F 4A 17 86 F0",
+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F "
+ "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"
+ /*"20 21 22 23"*/,
+ "C1 CF 48 A8 9F 2F FD D9 CF 46 52 E9 EF DB 72 D7 "
+ "45 40 A4 2B DE 6D 78 36 D5 9A 5C EA AE F3 10 53"
+ /*"25 B2 07 2F"*/
+ },
+ /* 192 bit key */
+ {
+ "16 AF 5B 14 5F C9 F5 79 C1 75 F9 3E 3B FB 0E ED "
+ "86 3D 06 CC FD B7 85 15 "
+ "00 00 00 48",
+ "36 73 3C 14 7D 6D 93 CB",
+ "53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67",
+ "4B 55 38 4F E2 59 C9 C8 4E 79 35 A0 03 CB E9 28",
+ },
+ {
+ "7C 5C B2 40 1B 3D C3 3C 19 E7 34 08 19 E0 F6 9C "
+ "67 8C 3D B8 E6 F6 A9 1A "
+ "00 96 B0 3B",
+ "02 0C 6E AD C2 CB 50 0D",
+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F "
+ "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F",
+ "45 32 43 FC 60 9B 23 32 7E DF AA FA 71 31 CD 9F "
+ "84 90 70 1C 5A D4 A7 9C FC 1F E0 FF 42 F4 FB 00",
+ },
+ {
+ "02 BF 39 1E E8 EC B1 59 B9 59 61 7B 09 65 27 9B "
+ "F5 9B 60 A7 86 D3 E0 FE "
+ "00 07 BD FD",
+ "5C BD 60 27 8D CC 09 12",
+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F "
+ "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"
+ /*"20 21 22 23"*/,
+ "96 89 3F C5 5E 5C 72 2F 54 0B 7D D1 DD F7 E7 58 "
+ "D2 88 BC 95 C6 91 65 88 45 36 C8 11 66 2F 21 88"
+ /*"AB EE 09 35"*/,
+ },
+ /* 256 bit key */
+ {
+ "77 6B EF F2 85 1D B0 6F 4C 8A 05 42 C8 69 6F 6C "
+ "6A 81 AF 1E EC 96 B4 D3 7F C1 D6 89 E6 C1 C1 04 "
+ "00 00 00 60",
+ "DB 56 72 C9 7A A8 F0 B2",
+ "53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67",
+ "14 5A D0 1D BF 82 4E C7 56 08 63 DC 71 E3 E0 C0"
+ },
+ {
+ "F6 D6 6D 6B D5 2D 59 BB 07 96 36 58 79 EF F8 86 "
+ "C6 6D D5 1A 5B 6A 99 74 4B 50 59 0C 87 A2 38 84 "
+ "00 FA AC 24",
+ "C1 58 5E F1 5A 43 D8 75",
+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F "
+ "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F",
+ "F0 5E 23 1B 38 94 61 2C 49 EE 00 0B 80 4E B2 A9 "
+ "B8 30 6B 50 8F 83 9D 6A 55 30 83 1D 93 44 AF 1C",
+ },
+ {
+ "FF 7A 61 7C E6 91 48 E4 F1 72 6E 2F 43 58 1D E2 "
+ "AA 62 D9 F8 05 53 2E DF F1 EE D6 87 FB 54 15 3D "
+ "00 1C C5 B7",
+ "51 A5 1D 70 A1 C1 11 48",
+ "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F "
+ "10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"
+ /*"20 21 22 23"*/,
+ "EB 6C 52 82 1D 0B BB F7 CE 75 94 46 2A CA 4F AA "
+ "B4 07 DF 86 65 69 FD 07 F4 8C C0 B5 83 D6 07 1F"
+ /*"1E C0 E6 B8"*/,
+ },
+};
+
+static int
+syscrypt(const unsigned char *key, size_t klen, const unsigned char *iv,
+ const unsigned char *in, unsigned char *out, size_t len, int encrypt)
+{
+ struct session_op session;
+ struct crypt_op cryp;
+ int cryptodev_fd = -1, fd = -1;
+
+ if ((cryptodev_fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
+ warn("/dev/crypto");
+ goto err;
+ }
+ if (ioctl(cryptodev_fd, CRIOGET, &fd) == -1) {
+ warn("CRIOGET failed");
+ goto err;
+ }
+ memset(&session, 0, sizeof(session));
+ session.cipher = CRYPTO_AES_CTR;
+ session.key = (caddr_t) key;
+ session.keylen = klen;
+ if (ioctl(fd, CIOCGSESSION, &session) == -1) {
+ warn("CIOCGSESSION");
+ goto err;
+ }
+ memset(&cryp, 0, sizeof(cryp));
+ cryp.ses = session.ses;
+ cryp.op = encrypt ? COP_ENCRYPT : COP_DECRYPT;
+ cryp.flags = 0;
+ cryp.len = len;
+ cryp.src = (caddr_t) in;
+ cryp.dst = (caddr_t) out;
+ cryp.iv = (caddr_t) iv;
+ cryp.mac = 0;
+ if (ioctl(fd, CIOCCRYPT, &cryp) == -1) {
+ warn("CIOCCRYPT");
+ goto err;
+ }
+ if (ioctl(fd, CIOCFSESSION, &session.ses) == -1) {
+ warn("CIOCFSESSION");
+ goto err;
+ }
+ close(fd);
+ close(cryptodev_fd);
+ return (0);
+
+err:
+ if (fd != -1)
+ close(fd);
+ if (cryptodev_fd != -1)
+ close(cryptodev_fd);
+ return (-1);
+}
+
+static int
+getallowsoft(void)
+{
+ int mib[2], old;
+ size_t olen;
+
+ olen = sizeof(old);
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_CRYPTODEVALLOWSOFT;
+ if (sysctl(mib, 2, &old, &olen, NULL, 0) < 0)
+ err(1, "sysctl failed");
+
+ return old;
+}
+
+static void
+setallowsoft(int new)
+{
+ int mib[2], old;
+ size_t olen, nlen;
+
+ olen = nlen = sizeof(new);
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_CRYPTODEVALLOWSOFT;
+
+ if (sysctl(mib, 2, &old, &olen, &new, nlen) < 0)
+ err(1, "sysctl failed");
+}
+
+static int
+match(unsigned char *a, unsigned char *b, size_t len)
+{
+ int i;
+
+ if (memcmp(a, b, len) == 0)
+ return (1);
+
+ warnx("ciphertext mismatch");
+
+ for (i = 0; i < len; i++)
+ printf("%2.2x", a[i]);
+ printf("\n");
+ for (i = 0; i < len; i++)
+ printf("%2.2x", b[i]);
+ printf("\n");
+
+ return (0);
+}
+
+static int
+run(int num)
+{
+ int i, fail = 1, len, j, length[TST_NUM];
+ u_long val;
+ char *ep, *from;
+ u_char *p, *data[TST_NUM];
+
+ for (i = 0; i < TST_NUM; i++)
+ data[i] = NULL;
+ for (i = 0; i < TST_NUM; i++) {
+ from = tests[num].data[i];
+ if (debug)
+ printf("%s\n", from);
+ len = strlen(from);
+ if ((p = malloc(len)) == 0) {
+ warn("malloc");
+ goto done;
+ }
+ errno = 0;
+ for (j = 0; j < len; j++) {
+ val = strtoul(&from[j*3], &ep, 16);
+ p[j] = (u_char)val;
+ if (*ep == '\0' || errno)
+ break;
+ }
+ length[i] = j+1;
+ data[i] = p;
+ }
+ len = length[TST_PLAIN];
+ if ((p = malloc(len)) == 0) {
+ warn("malloc");
+ return (1);
+ }
+ if (syscrypt(data[TST_KEY], length[TST_KEY],
+ data[TST_IV], data[TST_PLAIN], p,
+ length[TST_PLAIN], 0) < 0) {
+ warnx("crypt with /dev/crypto failed");
+ goto done;
+ }
+ fail = !match(data[TST_CIPHER], p, len);
+ printf("%s test vector %d\n", fail ? "FAILED" : "OK", num);
+done:
+ for (i = 0; i < TST_NUM; i++)
+ free(data[i]);
+ return (fail);
+}
+
+int
+main(int argc, char **argv)
+{
+ int allowed = 0, fail = 0, i;
+
+ if (geteuid() == 0) {
+ allowed = getallowsoft();
+ if (allowed == 0)
+ setallowsoft(1);
+ }
+ for (i = 0; i < (sizeof(tests) / sizeof(tests[0])); i++)
+ fail += run(i);
+ if (geteuid() == 0 && allowed == 0)
+ setallowsoft(0);
+ exit((fail > 0) ? 1 : 0);
+}
diff --git a/sys/crypto/cryptodev.c b/sys/crypto/cryptodev.c
index 7325da55281..bd1e888d368 100644
--- a/sys/crypto/cryptodev.c
+++ b/sys/crypto/cryptodev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cryptodev.c,v 1.62 2004/05/07 14:42:26 millert Exp $ */
+/* $OpenBSD: cryptodev.c,v 1.63 2005/05/25 05:47:53 markus Exp $ */
/*
* Copyright (c) 2001 Theo de Raadt
@@ -173,6 +173,9 @@ cryptof_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
case CRYPTO_AES_CBC:
txform = &enc_xform_rijndael128;
break;
+ case CRYPTO_AES_CTR:
+ txform = &enc_xform_aes_ctr;
+ break;
case CRYPTO_ARC4:
txform = &enc_xform_arc4;
break;
diff --git a/sys/crypto/cryptodev.h b/sys/crypto/cryptodev.h
index eac54325840..e14b18b56e0 100644
--- a/sys/crypto/cryptodev.h
+++ b/sys/crypto/cryptodev.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cryptodev.h,v 1.42 2003/08/14 15:18:05 jason Exp $ */
+/* $OpenBSD: cryptodev.h,v 1.43 2005/05/25 05:47:53 markus Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
@@ -96,7 +96,8 @@
#define CRYPTO_SHA2_256_HMAC 18
#define CRYPTO_SHA2_384_HMAC 19
#define CRYPTO_SHA2_512_HMAC 20
-#define CRYPTO_ALGORITHM_MAX 20 /* Keep updated - see below */
+#define CRYPTO_AES_CTR 21
+#define CRYPTO_ALGORITHM_MAX 21 /* Keep updated - see below */
#define CRYPTO_ALGORITHM_ALL (CRYPTO_ALGORITHM_MAX + 1)
diff --git a/sys/crypto/cryptosoft.c b/sys/crypto/cryptosoft.c
index e1fdd00cae4..a96a317dd71 100644
--- a/sys/crypto/cryptosoft.c
+++ b/sys/crypto/cryptosoft.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cryptosoft.c,v 1.44 2005/05/10 13:42:11 markus Exp $ */
+/* $OpenBSD: cryptosoft.c,v 1.45 2005/05/25 05:47:53 markus Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
@@ -82,21 +82,18 @@ swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN], *idat;
unsigned char *ivp, piv[EALG_MAX_BLOCK_LEN];
struct enc_xform *exf;
- int i, k, j, blks, ind, count;
+ int i, k, j, blks, ind, count, ivlen;
struct mbuf *m = NULL;
struct uio *uio = NULL;
-
exf = sw->sw_exf;
blks = exf->blocksize;
+ ivlen = exf->ivsize;
/* Check for non-padded data */
if (crd->crd_len % blks)
return EINVAL;
- if (exf == &enc_xform_null)
- return (0);
-
if (outtype == CRYPTO_BUF_MBUF)
m = (struct mbuf *) buf;
else
@@ -106,27 +103,30 @@ swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
if (crd->crd_flags & CRD_F_ENCRYPT) {
/* IV explicitly provided ? */
if (crd->crd_flags & CRD_F_IV_EXPLICIT)
- bcopy(crd->crd_iv, iv, blks);
+ bcopy(crd->crd_iv, iv, ivlen);
else
- arc4random_bytes(iv, blks);
+ arc4random_bytes(iv, ivlen);
/* Do we need to write the IV */
if (!(crd->crd_flags & CRD_F_IV_PRESENT)) {
- COPYBACK(outtype, buf, crd->crd_inject, blks, iv);
+ COPYBACK(outtype, buf, crd->crd_inject, ivlen, iv);
}
} else { /* Decryption */
/* IV explicitly provided ? */
if (crd->crd_flags & CRD_F_IV_EXPLICIT)
- bcopy(crd->crd_iv, iv, blks);
+ bcopy(crd->crd_iv, iv, ivlen);
else {
/* Get IV off buf */
- COPYDATA(outtype, buf, crd->crd_inject, blks, iv);
+ COPYDATA(outtype, buf, crd->crd_inject, ivlen, iv);
}
}
ivp = iv;
+ if (exf->reinit)
+ exf->reinit(sw->sw_kschedule, iv);
+
if (outtype == CRYPTO_BUF_MBUF) {
/* Find beginning of data */
m = m_getptr(m, crd->crd_skip, &k);
@@ -144,7 +144,9 @@ swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
m_copydata(m, k, blks, blk);
/* Actual encryption/decryption */
- if (crd->crd_flags & CRD_F_ENCRYPT) {
+ if (exf->reinit) {
+ exf->encrypt(sw->sw_kschedule, blk);
+ } else if (crd->crd_flags & CRD_F_ENCRYPT) {
/* XOR with previous block */
for (j = 0; j < blks; j++)
blk[j] ^= ivp[j];
@@ -214,7 +216,9 @@ swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
idat = mtod(m, unsigned char *) + k;
while (m->m_len >= k + blks && i > 0) {
- if (crd->crd_flags & CRD_F_ENCRYPT) {
+ if (exf->reinit) {
+ exf->encrypt(sw->sw_kschedule, idat);
+ } else if (crd->crd_flags & CRD_F_ENCRYPT) {
/* XOR with previous block/IV */
for (j = 0; j < blks; j++)
idat[j] ^= ivp[j];
@@ -267,7 +271,9 @@ swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
cuio_copydata(uio, k, blks, blk);
/* Actual encryption/decryption */
- if (crd->crd_flags & CRD_F_ENCRYPT) {
+ if (exf->reinit) {
+ exf->encrypt(sw->sw_kschedule, blk);
+ } else if (crd->crd_flags & CRD_F_ENCRYPT) {
/* XOR with previous block */
for (j = 0; j < blks; j++)
blk[j] ^= ivp[j];
@@ -328,7 +334,9 @@ swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
while (uio->uio_iov[ind].iov_len >= k + blks &&
i > 0) {
- if (crd->crd_flags & CRD_F_ENCRYPT) {
+ if (exf->reinit) {
+ exf->encrypt(sw->sw_kschedule, idat);
+ } else if (crd->crd_flags & CRD_F_ENCRYPT) {
/* XOR with previous block/IV */
for (j = 0; j < blks; j++)
idat[j] ^= ivp[j];
@@ -599,6 +607,9 @@ swcr_newsession(u_int32_t *sid, struct cryptoini *cri)
case CRYPTO_RIJNDAEL128_CBC:
txf = &enc_xform_rijndael128;
goto enccommon;
+ case CRYPTO_AES_CTR:
+ txf = &enc_xform_aes_ctr;
+ goto enccommon;
case CRYPTO_NULL:
txf = &enc_xform_null;
goto enccommon;
@@ -760,6 +771,7 @@ swcr_freesession(u_int64_t tid)
case CRYPTO_CAST_CBC:
case CRYPTO_SKIPJACK_CBC:
case CRYPTO_RIJNDAEL128_CBC:
+ case CRYPTO_AES_CTR:
case CRYPTO_NULL:
txf = swd->sw_exf;
@@ -868,13 +880,15 @@ swcr_process(struct cryptop *crp)
}
switch (sw->sw_alg) {
+ case CRYPTO_NULL:
+ break;
case CRYPTO_DES_CBC:
case CRYPTO_3DES_CBC:
case CRYPTO_BLF_CBC:
case CRYPTO_CAST_CBC:
case CRYPTO_SKIPJACK_CBC:
case CRYPTO_RIJNDAEL128_CBC:
- case CRYPTO_NULL:
+ case CRYPTO_AES_CTR:
if ((crp->crp_etype = swcr_encdec(crd, sw,
crp->crp_buf, type)) != 0)
goto done;
@@ -945,6 +959,7 @@ swcr_init(void)
algs[CRYPTO_MD5] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_SHA1] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_RIJNDAEL128_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
+ algs[CRYPTO_AES_CTR] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_DEFLATE_COMP] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_NULL] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_SHA2_256_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
diff --git a/sys/crypto/rijndael.c b/sys/crypto/rijndael.c
index e1dcb0dae64..1edca913680 100644
--- a/sys/crypto/rijndael.c
+++ b/sys/crypto/rijndael.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rijndael.c,v 1.17 2004/12/20 20:31:18 hshoexer Exp $ */
+/* $OpenBSD: rijndael.c,v 1.18 2005/05/25 05:47:53 markus Exp $ */
/**
* rijndael-alg-fst.c
@@ -851,7 +851,7 @@ rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits)
return Nr;
}
-static void
+void
rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16],
u8 ct[16])
{
diff --git a/sys/crypto/rijndael.h b/sys/crypto/rijndael.h
index 6b509576c6a..190b4c5f555 100644
--- a/sys/crypto/rijndael.h
+++ b/sys/crypto/rijndael.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rijndael.h,v 1.10 2004/12/20 20:31:18 hshoexer Exp $ */
+/* $OpenBSD: rijndael.h,v 1.11 2005/05/25 05:47:53 markus Exp $ */
/**
* rijndael-alg-fst.h
@@ -51,5 +51,7 @@ void rijndael_encrypt(rijndael_ctx *, u_char *, u_char *);
int rijndaelKeySetupEnc(unsigned int [], const unsigned char [], int);
int rijndaelKeySetupDec(unsigned int [], const unsigned char [], int);
+void rijndaelEncrypt(const unsigned int [], int, const unsigned char [],
+ unsigned char []);
#endif /* __RIJNDAEL_H */
diff --git a/sys/crypto/xform.c b/sys/crypto/xform.c
index c9f42a648e4..b0b9b513092 100644
--- a/sys/crypto/xform.c
+++ b/sys/crypto/xform.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xform.c,v 1.28 2004/12/20 20:31:18 hshoexer Exp $ */
+/* $OpenBSD: xform.c,v 1.29 2005/05/25 05:47:53 markus Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -67,6 +67,7 @@ int blf_setkey(u_int8_t **, u_int8_t *, int);
int cast5_setkey(u_int8_t **, u_int8_t *, int);
int skipjack_setkey(u_int8_t **, u_int8_t *, int);
int rijndael128_setkey(u_int8_t **, u_int8_t *, int);
+int aes_ctr_setkey(u_int8_t **, u_int8_t *, int);
void des1_encrypt(caddr_t, u_int8_t *);
void des3_encrypt(caddr_t, u_int8_t *);
void blf_encrypt(caddr_t, u_int8_t *);
@@ -85,11 +86,15 @@ void blf_zerokey(u_int8_t **);
void cast5_zerokey(u_int8_t **);
void skipjack_zerokey(u_int8_t **);
void rijndael128_zerokey(u_int8_t **);
+void aes_ctr_zerokey(u_int8_t **);
void null_encrypt(caddr_t, u_int8_t *);
void null_zerokey(u_int8_t **);
int null_setkey(u_int8_t **, u_int8_t *, int);
void null_decrypt(caddr_t, u_int8_t *);
+void aes_ctr_reinit(caddr_t, u_int8_t *);
+void aes_ctr_crypt(caddr_t, u_int8_t *);
+
int MD5Update_int(void *, u_int8_t *, u_int16_t);
int SHA1Update_int(void *, u_int8_t *, u_int16_t);
int RMD160Update_int(void *, u_int8_t *, u_int16_t);
@@ -104,74 +109,92 @@ u_int32_t lzs_dummy(u_int8_t *, u_int32_t, u_int8_t **);
/* Encryption instances */
struct enc_xform enc_xform_des = {
CRYPTO_DES_CBC, "DES",
- 8, 8, 8,
+ 8, 8, 8, 8,
des1_encrypt,
des1_decrypt,
des1_setkey,
des1_zerokey,
+ NULL
};
struct enc_xform enc_xform_3des = {
CRYPTO_3DES_CBC, "3DES",
- 8, 24, 24,
+ 8, 8, 24, 24,
des3_encrypt,
des3_decrypt,
des3_setkey,
- des3_zerokey
+ des3_zerokey,
+ NULL
};
struct enc_xform enc_xform_blf = {
CRYPTO_BLF_CBC, "Blowfish",
- 8, 5, 56 /* 448 bits, max key */,
+ 8, 8, 5, 56 /* 448 bits, max key */,
blf_encrypt,
blf_decrypt,
blf_setkey,
- blf_zerokey
+ blf_zerokey,
+ NULL
};
struct enc_xform enc_xform_cast5 = {
CRYPTO_CAST_CBC, "CAST-128",
- 8, 5, 16,
+ 8, 8, 5, 16,
cast5_encrypt,
cast5_decrypt,
cast5_setkey,
- cast5_zerokey
+ cast5_zerokey,
+ NULL
};
struct enc_xform enc_xform_skipjack = {
CRYPTO_SKIPJACK_CBC, "Skipjack",
- 8, 10, 10,
+ 8, 8, 10, 10,
skipjack_encrypt,
skipjack_decrypt,
skipjack_setkey,
- skipjack_zerokey
+ skipjack_zerokey,
+ NULL
};
struct enc_xform enc_xform_rijndael128 = {
CRYPTO_RIJNDAEL128_CBC, "Rijndael-128/AES",
- 16, 16, 32,
+ 16, 16, 16, 32,
rijndael128_encrypt,
rijndael128_decrypt,
rijndael128_setkey,
rijndael128_zerokey,
+ NULL
+};
+
+struct enc_xform enc_xform_aes_ctr = {
+ CRYPTO_AES_CTR, "AES-CTR",
+ 16, 8, 16+4, 32+4,
+ aes_ctr_crypt,
+ NULL,
+ aes_ctr_setkey,
+ aes_ctr_zerokey,
+ aes_ctr_reinit
};
struct enc_xform enc_xform_arc4 = {
CRYPTO_ARC4, "ARC4",
- 1, 1, 32,
+ 1, 1, 1, 32,
NULL,
NULL,
NULL,
NULL,
+ NULL
};
struct enc_xform enc_xform_null = {
CRYPTO_NULL, "NULL",
- 8, 24, 24,
+ 1, 0, 0, 256,
null_encrypt,
null_decrypt,
null_setkey,
null_zerokey,
+ NULL
};
/* Authentication instances */
@@ -486,6 +509,76 @@ rijndael128_zerokey(u_int8_t **sched)
*sched = NULL;
}
+#define AESCTR_NONCESIZE 4
+#define AESCTR_IVSIZE 8
+#define AESCTR_BLOCKSIZE 16
+
+struct aes_ctr_ctx {
+ u_int32_t ac_ek[4*(MAXNR + 1)];
+ u_int8_t ac_block[AESCTR_BLOCKSIZE];
+ int ac_nr;
+};
+
+void
+aes_ctr_reinit(caddr_t key, u_int8_t *iv)
+{
+ struct aes_ctr_ctx *ctx;
+
+ ctx = (struct aes_ctr_ctx *)key;
+ bcopy(iv, ctx->ac_block + AESCTR_NONCESIZE, AESCTR_IVSIZE);
+
+ /* reset counter */
+ bzero(ctx->ac_block + AESCTR_NONCESIZE + AESCTR_IVSIZE, 4);
+}
+
+void
+aes_ctr_crypt(caddr_t key, u_int8_t *data)
+{
+ struct aes_ctr_ctx *ctx;
+ u_int8_t keystream[AESCTR_BLOCKSIZE];
+ int i;
+
+ ctx = (struct aes_ctr_ctx *)key;
+ /* increment counter */
+ for (i = AESCTR_BLOCKSIZE - 1;
+ i >= AESCTR_NONCESIZE + AESCTR_IVSIZE; i--)
+ if (++ctx->ac_block[i]) /* continue on overflow */
+ break;
+ rijndaelEncrypt(ctx->ac_ek, ctx->ac_nr, ctx->ac_block, keystream);
+ for (i = 0; i < AESCTR_BLOCKSIZE; i++)
+ data[i] ^= keystream[i];
+}
+
+int
+aes_ctr_setkey(u_int8_t **sched, u_int8_t *key, int len)
+{
+ struct aes_ctr_ctx *ctx;
+
+ if (len < AESCTR_NONCESIZE)
+ return -1;
+
+ MALLOC(*sched, u_int8_t *, sizeof(struct aes_ctr_ctx), M_CRYPTO_DATA,
+ M_WAITOK);
+ bzero(*sched, sizeof(struct aes_ctr_ctx));
+ ctx = (struct aes_ctr_ctx *)*sched;
+ ctx->ac_nr = rijndaelKeySetupEnc(ctx->ac_ek, (u_char *)key,
+ (len - AESCTR_NONCESIZE) * 8);
+ if (ctx->ac_nr == 0) {
+ aes_ctr_zerokey(sched);
+ return -1;
+ }
+ bcopy(key + len - AESCTR_NONCESIZE, ctx->ac_block, AESCTR_NONCESIZE);
+ return 0;
+}
+
+void
+aes_ctr_zerokey(u_int8_t **sched)
+{
+ bzero(*sched, sizeof(struct aes_ctr_ctx));
+ FREE(*sched, M_CRYPTO_DATA);
+ *sched = NULL;
+}
+
/*
* And now for auth.
*/
diff --git a/sys/crypto/xform.h b/sys/crypto/xform.h
index fa7838665c2..b2e19c99ed2 100644
--- a/sys/crypto/xform.h
+++ b/sys/crypto/xform.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: xform.h,v 1.15 2004/12/20 20:31:18 hshoexer Exp $ */
+/* $OpenBSD: xform.h,v 1.16 2005/05/25 05:47:53 markus Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
@@ -45,12 +45,13 @@ struct auth_hash {
struct enc_xform {
int type;
char *name;
- u_int16_t blocksize;
+ u_int16_t blocksize, ivsize;
u_int16_t minkey, maxkey;
void (*encrypt) (caddr_t, u_int8_t *);
void (*decrypt) (caddr_t, u_int8_t *);
int (*setkey) (u_int8_t **, u_int8_t *, int len);
void (*zerokey) (u_int8_t **);
+ void (*reinit) (caddr_t, u_int8_t *);
};
struct comp_algo {
@@ -76,6 +77,7 @@ extern struct enc_xform enc_xform_blf;
extern struct enc_xform enc_xform_cast5;
extern struct enc_xform enc_xform_skipjack;
extern struct enc_xform enc_xform_rijndael128;
+extern struct enc_xform enc_xform_aes_ctr;
extern struct enc_xform enc_xform_arc4;
extern struct enc_xform enc_xform_null;
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c
index 770c301048a..8abc1dca9ee 100644
--- a/sys/net/pfkeyv2.c
+++ b/sys/net/pfkeyv2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2.c,v 1.103 2005/05/24 03:13:53 ho Exp $ */
+/* $OpenBSD: pfkeyv2.c,v 1.104 2005/05/25 05:47:53 markus Exp $ */
/*
* @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
@@ -100,7 +100,8 @@ static const struct sadb_alg ealgs[] = {
{ SADB_X_EALG_BLF, 64, 40, BLF_MAXKEYLEN * 8},
{ SADB_X_EALG_CAST, 64, 40, 128},
{ SADB_X_EALG_SKIPJACK, 64, 80, 80},
- { SADB_X_EALG_AES, 128, 64, 256}
+ { SADB_X_EALG_AES, 128, 128, 256},
+ { SADB_X_EALG_AESCTR, 128, 128 + 32, 256 + 32}
};
static const struct sadb_alg aalgs[] = {
@@ -1958,8 +1959,13 @@ pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw,
if (!strncasecmp(ipsec_def_enc, "aes",
sizeof("aes"))) {
sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AES;
- sadb_comb->sadb_comb_encrypt_minbits = 64;
+ sadb_comb->sadb_comb_encrypt_minbits = 128;
sadb_comb->sadb_comb_encrypt_maxbits = 256;
+ } else if (!strncasecmp(ipsec_def_enc, "aesctr",
+ sizeof("aesctr"))) {
+ sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AESCTR;
+ sadb_comb->sadb_comb_encrypt_minbits = 128+32;
+ sadb_comb->sadb_comb_encrypt_maxbits = 256+32;
} else if (!strncasecmp(ipsec_def_enc, "3des",
sizeof("3des"))) {
sadb_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC;
diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h
index 1ad5702a79a..4738ffd66ce 100644
--- a/sys/net/pfkeyv2.h
+++ b/sys/net/pfkeyv2.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2.h,v 1.53 2005/04/04 22:18:47 hshoexer Exp $ */
+/* $OpenBSD: pfkeyv2.h,v 1.54 2005/05/25 05:47:53 markus Exp $ */
/*
* @(#)COPYRIGHT 1.1 (NRL) January 1998
*
@@ -299,6 +299,7 @@ struct sadb_x_udpencap {
#define SADB_X_EALG_RC4 10
#define SADB_EALG_NULL 11
#define SADB_X_EALG_AES 12
+#define SADB_X_EALG_AESCTR 13
#define SADB_X_EALG_SKIPJACK 249
#define SADB_EALG_MAX 249
diff --git a/sys/net/pfkeyv2_convert.c b/sys/net/pfkeyv2_convert.c
index 0c7f1963414..43b24904338 100644
--- a/sys/net/pfkeyv2_convert.c
+++ b/sys/net/pfkeyv2_convert.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2_convert.c,v 1.23 2005/05/24 02:30:03 ho Exp $ */
+/* $OpenBSD: pfkeyv2_convert.c,v 1.24 2005/05/25 05:47:53 markus Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@keromytis.org)
*
@@ -232,6 +232,10 @@ export_sa(void **p, struct tdb *tdb)
sadb_sa->sadb_sa_encrypt = SADB_X_EALG_AES;
break;
+ case CRYPTO_AES_CTR:
+ sadb_sa->sadb_sa_encrypt = SADB_X_EALG_AESCTR;
+ break;
+
case CRYPTO_CAST_CBC:
sadb_sa->sadb_sa_encrypt = SADB_X_EALG_CAST;
break;
diff --git a/sys/netinet/ip_esp.c b/sys/netinet/ip_esp.c
index 47cff502423..26f2a1eff29 100644
--- a/sys/netinet/ip_esp.c
+++ b/sys/netinet/ip_esp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp.c,v 1.89 2005/05/10 13:42:11 markus Exp $ */
+/* $OpenBSD: ip_esp.c,v 1.90 2005/05/25 05:47:53 markus Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -113,6 +113,10 @@ esp_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
txform = &enc_xform_rijndael128;
break;
+ case SADB_X_EALG_AESCTR:
+ txform = &enc_xform_aes_ctr;
+ break;
+
case SADB_X_EALG_BLF:
txform = &enc_xform_blf;
break;
@@ -145,10 +149,7 @@ esp_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
DPRINTF(("esp_init(): initialized TDB with enc algorithm %s\n",
txform->name));
- if (ii->ii_encalg == SADB_EALG_NULL)
- tdbp->tdb_ivlen = 0;
- else
- tdbp->tdb_ivlen = txform->blocksize;
+ tdbp->tdb_ivlen = txform->ivsize;
if (tdbp->tdb_flags & TDBF_HALFIV)
tdbp->tdb_ivlen /= 2;
}