summaryrefslogtreecommitdiff
path: root/sys/netinet/ip_esp_new.c
diff options
context:
space:
mode:
authorNiels Provos <provos@cvs.openbsd.org>1997-11-04 09:11:18 +0000
committerNiels Provos <provos@cvs.openbsd.org>1997-11-04 09:11:18 +0000
commit99655e667eb6f6f401a446b7c40091b28014ae9b (patch)
tree5874363a52f49f43149aa8792a34d9f0bef8e63b /sys/netinet/ip_esp_new.c
parentb5f0a5904ec6fadc4a3b9c6135c788a2fc280740 (diff)
make it easier to add additional transforms. add blowfish and cast
encryption. some more info for kernfs/ipsec.
Diffstat (limited to 'sys/netinet/ip_esp_new.c')
-rw-r--r--sys/netinet/ip_esp_new.c542
1 files changed, 239 insertions, 303 deletions
diff --git a/sys/netinet/ip_esp_new.c b/sys/netinet/ip_esp_new.c
index 53fe1a8b454..b26e0e9c4da 100644
--- a/sys/netinet/ip_esp_new.c
+++ b/sys/netinet/ip_esp_new.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp_new.c,v 1.9 1997/10/02 02:31:04 deraadt Exp $ */
+/* $OpenBSD: ip_esp_new.c,v 1.10 1997/11/04 09:11:11 provos Exp $ */
/*
* The author of this code is John Ioannidis, ji@tla.org,
@@ -9,7 +9,11 @@
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis, kermit@forthnet.gr.
*
- * Copyright (C) 1995, 1996, 1997 by John Ioannidis and Angelos D. Keromytis.
+ * Additional transforms and features in 1997 by Angelos D. Keromytis and
+ * Niels Provos.
+ *
+ * Copyright (C) 1995, 1996, 1997 by John Ioannidis, Angelos D. Keromytis
+ * and Niels Provos.
*
* Permission to use, copy, and modify this software without fee
* is hereby granted, provided that this entire notice is included in
@@ -66,6 +70,121 @@ extern void des_ecb3_encrypt(caddr_t, caddr_t, caddr_t, caddr_t, caddr_t, int);
extern void des_ecb_encrypt(caddr_t, caddr_t, caddr_t, int);
extern void des_set_key(caddr_t, caddr_t);
+static void des1_encrypt(void *, u_int8_t *);
+static void des3_encrypt(void *, u_int8_t *);
+static void blf_encrypt(void *, u_int8_t *);
+static void cast5_encrypt(void *, u_int8_t *);
+static void des1_decrypt(void *, u_int8_t *);
+static void des3_decrypt(void *, u_int8_t *);
+static void blf_decrypt(void *, u_int8_t *);
+static void cast5_decrypt(void *, u_int8_t *);
+
+struct esp_hash esp_new_hash[] = {
+ { ALG_AUTH_MD5, "HMAC-MD5-96",
+ AH_MD5_ALEN,
+ sizeof(MD5_CTX),
+ (void (*)(void *))MD5Init,
+ (void (*)(void *, u_int8_t *, u_int16_t))MD5Update,
+ (void (*)(u_int8_t *, void *))MD5Final
+ },
+ { ALG_AUTH_SHA1, "HMAC-SHA1-96",
+ AH_SHA1_ALEN,
+ sizeof(SHA1_CTX),
+ (void (*)(void *))SHA1Init,
+ (void (*)(void *, u_int8_t *, u_int16_t))SHA1Update,
+ (void (*)(u_int8_t *, void *))SHA1Final
+ }
+};
+
+struct esp_xform esp_new_xform[] = {
+ { ALG_ENC_DES, "Data Encryption Standard (DES)",
+ ESP_DES_BLKS, ESP_DES_IVS,
+ 8, 8, 8 | 1,
+ des1_encrypt,
+ des1_decrypt
+ },
+ { ALG_ENC_3DES, "Tripple DES (3DES)",
+ ESP_3DES_BLKS, ESP_3DES_IVS,
+ 24, 24, 8 | 1,
+ des3_encrypt,
+ des3_decrypt
+ },
+ { ALG_ENC_BLF, "Blowfish",
+ ESP_BLF_BLKS, ESP_BLF_IVS,
+ 5, BLF_MAXKEYLEN, 8,
+ blf_encrypt,
+ blf_decrypt
+ },
+ { ALG_ENC_CAST, "CAST",
+ ESP_CAST_BLKS, ESP_CAST_IVS,
+ 5, 16, 8,
+ cast5_encrypt,
+ cast5_decrypt
+ }
+};
+
+static void
+des1_encrypt(void *pxd, u_int8_t *blk)
+{
+ struct esp_new_xdata *xd = pxd;
+ des_ecb_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]), 1);
+}
+
+static void
+des1_decrypt(void *pxd, u_int8_t *blk)
+{
+ struct esp_new_xdata *xd = pxd;
+ des_ecb_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]), 0);
+}
+
+static void
+des3_encrypt(void *pxd, u_int8_t *blk)
+{
+ struct esp_new_xdata *xd = pxd;
+ des_ecb3_encrypt(blk, blk, (caddr_t) (xd->edx_eks[2]),
+ (caddr_t) (xd->edx_eks[1]),
+ (caddr_t) (xd->edx_eks[0]), 1);
+}
+
+static void
+des3_decrypt(void *pxd, u_int8_t *blk)
+{
+ struct esp_new_xdata *xd = pxd;
+ des_ecb3_encrypt(blk, blk, (caddr_t) (xd->edx_eks[2]),
+ (caddr_t) (xd->edx_eks[1]),
+ (caddr_t) (xd->edx_eks[0]), 0);
+}
+
+static void
+blf_encrypt(void *pxd, u_int8_t *blk)
+{
+ struct esp_new_xdata *xd = pxd;
+ Blowfish_encipher(&xd->edx_bks, (u_int32_t *)blk,
+ (u_int32_t *)(blk+4));
+}
+
+static void
+blf_decrypt(void *pxd, u_int8_t *blk)
+{
+ struct esp_new_xdata *xd = pxd;
+ Blowfish_decipher(&xd->edx_bks, (u_int32_t *)blk,
+ (u_int32_t *)(blk+4));
+}
+
+static void
+cast5_encrypt(void *pxd, u_int8_t *blk)
+{
+ struct esp_new_xdata *xd = pxd;
+ cast_encrypt(&xd->edx_cks, blk, blk);
+}
+
+static void
+cast5_decrypt(void *pxd, u_int8_t *blk)
+{
+ struct esp_new_xdata *xd = pxd;
+ cast_decrypt(&xd->edx_cks, blk, blk);
+}
+
/*
* esp_new_attach() is called from the transformation initialization code.
* It just returns.
@@ -93,9 +212,11 @@ esp_new_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m)
struct esp_new_xdata *xd;
struct esp_new_xencap txd;
struct encap_msghdr *em;
+ struct esp_xform *txform;
+ struct esp_hash *thash;
caddr_t buffer = NULL;
- int blocklen, i, enc_keylen, auth_keylen;
- u_int32_t rk[6];
+ int blocklen, i;
+ u_int32_t rk[14];
if (m->m_len < ENCAP_MSG_FIXED_LEN)
{
@@ -121,91 +242,73 @@ esp_new_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m)
m_copydata(m, EMT_SETSPI_FLEN, ESP_NEW_XENCAP_LEN, (caddr_t) &txd);
/* Check whether the encryption algorithm is supported */
- switch (txd.edx_enc_algorithm)
+ for (i=sizeof(esp_new_xform)/sizeof(struct esp_xform)-1; i >= 0; i--)
+ if (txd.edx_enc_algorithm == esp_new_xform[i].type)
+ break;
+ if (i < 0)
{
- case ALG_ENC_DES:
- case ALG_ENC_3DES:
+ if (encdebug)
+ log(LOG_WARNING, "esp_new_init(): unsupported encryption algorithm %d specified\n", txd.edx_enc_algorithm);
+ return EINVAL;
+ }
+
+ txform = &esp_new_xform[i];
#ifdef ENCDEBUG
- if (encdebug)
- printf("esp_new_init(): initialized TDB with enc algorithm %d\n",
- txd.edx_enc_algorithm);
+ if (encdebug)
+ printf("esp_new_init(): initialized TDB with enc algorithm %d: %s\n",
+ txd.edx_enc_algorithm, esp_new_xform[i].name);
#endif /* ENCDEBUG */
- break;
- default:
- if (encdebug)
- log(LOG_WARNING, "esp_new_init(): unsupported encryption algorithm %d specified\n", txd.edx_enc_algorithm);
+ /* Check whether the authentication algorithm is supported */
+ if (txd.edx_flags & ESP_NEW_FLAG_AUTH)
+ {
+ for (i=sizeof(esp_new_hash)/sizeof(struct esp_hash)-1; i >= 0; i--)
+ if (txd.edx_hash_algorithm == esp_new_hash[i].type)
+ break;
+ if (i < 0)
+ {
+ if (encdebug)
+ log(LOG_WARNING, "esp_new_init(): unsupported authentication algorithm %d specified\n", txd.edx_hash_algorithm);
return EINVAL;
- }
+ }
- /* Check whether the authentication algorithm is supported */
- if (txd.edx_flags & ESP_NEW_FLAG_AUTH)
- switch (txd.edx_hash_algorithm)
- {
- case ALG_AUTH_MD5:
- case ALG_AUTH_SHA1:
#ifdef ENCDEBUG
- if (encdebug)
- printf("esp_new_init(): initialized TDB with hash algorithm %d\n", txd.edx_hash_algorithm);
+ if (encdebug)
+ printf("esp_new_init(): initialized TDB with hash algorithm %d: %s\n",
+ txd.edx_hash_algorithm, esp_new_hash[i].name);
#endif /* ENCDEBUG */
- blocklen = HMAC_BLOCK_LEN;
- break;
-
- default:
- if (encdebug)
- log(LOG_WARNING, "esp_new_init(): unsupported authentication algorithm %d specified\n", txd.edx_enc_algorithm);
- return EINVAL;
+ blocklen = HMAC_BLOCK_LEN;
+ thash = &esp_new_hash[i];
}
- if (txd.edx_ivlen + txd.edx_keylen + EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN
- != em->em_msglen)
+ if (txd.edx_ivlen + txd.edx_confkeylen + txd.edx_authkeylen +
+ EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN != em->em_msglen)
{
if (encdebug)
log(LOG_WARNING, "esp_new_init(): message length (%d) doesn't match\n", em->em_msglen);
return EINVAL;
}
- switch (txd.edx_enc_algorithm)
+ /* Check the IV length */
+ if (((txd.edx_ivlen == 0) && !(txform->ivmask&1)) ||
+ ((txd.edx_ivlen != 0) && (
+ !(txd.edx_ivlen & txform->ivmask) ||
+ (txd.edx_ivlen & (txd.edx_ivlen-1)))))
{
- case ALG_ENC_DES:
- if ((txd.edx_ivlen != 0) && (txd.edx_ivlen != 8))
- {
- if (encdebug)
- log(LOG_WARNING, "esp_new_init(): unsupported IV length %d\n",
- txd.edx_ivlen);
- return EINVAL;
- }
-
- if (txd.edx_keylen < 8)
- {
- if (encdebug)
- log(LOG_WARNING, "esp_new_init(): bad key length\n",
- txd.edx_keylen);
- return EINVAL;
- }
-
- enc_keylen = 8;
- break;
+ if (encdebug)
+ log(LOG_WARNING, "esp_new_init(): unsupported IV length %d\n",
+ txd.edx_ivlen);
+ return EINVAL;
+ }
- case ALG_ENC_3DES:
- if ((txd.edx_ivlen != 0) && (txd.edx_ivlen != 8))
- {
- if (encdebug)
- log(LOG_WARNING, "esp_new_init(): unsupported IV length %d\n",
- txd.edx_ivlen);
- return EINVAL;
- }
-
- if (txd.edx_keylen < 24)
- {
- if (encdebug)
- log(LOG_WARNING, "esp_new_init(): bad key length\n",
- txd.edx_keylen);
- return EINVAL;
- }
-
- enc_keylen = 24;
- break;
+ /* Check the key length */
+ if (txd.edx_confkeylen < txform->minkey ||
+ txd.edx_confkeylen > txform->maxkey)
+ {
+ if (encdebug)
+ log(LOG_WARNING, "esp_new_init(): bad key length %d\n",
+ txd.edx_confkeylen);
+ return EINVAL;
}
MALLOC(tdbp->tdb_xdata, caddr_t, sizeof(struct esp_new_xdata),
@@ -231,6 +334,10 @@ esp_new_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m)
xd->edx_flags = txd.edx_flags;
xd->edx_hash_algorithm = txd.edx_hash_algorithm;
xd->edx_bitmap = 0;
+ xd->edx_xform = txform;
+
+ /* Pass name of enc algorithm for kernfs */
+ tdbp->tdb_confname = xd->edx_xform->name;
/* Replay counters are mandatory, even without auth */
xd->edx_rpl = AH_HMAC_INITIAL_RPL;
@@ -239,39 +346,43 @@ esp_new_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m)
m_copydata(m, EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN, xd->edx_ivlen,
(caddr_t) xd->edx_iv);
+ /* Copy the key material */
+ m_copydata(m, EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN + xd->edx_ivlen,
+ txd.edx_confkeylen, (caddr_t) rk);
switch (xd->edx_enc_algorithm)
{
case ALG_ENC_DES:
- /* Copy the key material */
- m_copydata(m, EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN + xd->edx_ivlen,
- enc_keylen, (caddr_t) rk);
-
des_set_key((caddr_t) rk, (caddr_t) (xd->edx_eks[0]));
break;
case ALG_ENC_3DES:
- /* Copy the key material */
- m_copydata(m, EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN + xd->edx_ivlen,
- enc_keylen, (caddr_t) rk);
-
des_set_key((caddr_t) rk, (caddr_t) (xd->edx_eks[0]));
des_set_key((caddr_t) (rk + 2), (caddr_t) (xd->edx_eks[1]));
des_set_key((caddr_t) (rk + 4), (caddr_t) (xd->edx_eks[2]));
break;
+ case ALG_ENC_BLF:
+ blf_key(&xd->edx_bks, (caddr_t) rk, txd.edx_confkeylen);
+ break;
+ case ALG_ENC_CAST:
+ cast_setkey(&xd->edx_cks, (caddr_t) rk, txd.edx_confkeylen);
+ break;
}
if (txd.edx_flags & ESP_NEW_FLAG_AUTH)
{
- auth_keylen = txd.edx_keylen - enc_keylen;
+ xd->edx_hash = thash;
+
+ /* Pass name of auth algorithm for kernfs */
+ tdbp->tdb_authname = xd->edx_hash->name;
#ifdef ENCDEBUG
if (encdebug)
printf("esp_new_init(): using %d bytes of authentication key\n",
- auth_keylen);
+ txd.edx_authkeylen);
#endif
MALLOC(buffer, caddr_t,
- auth_keylen < blocklen ? blocklen : auth_keylen,
+ txd.edx_authkeylen < blocklen ? blocklen : txd.edx_authkeylen,
M_TEMP, M_WAITOK);
if (buffer == NULL)
{
@@ -283,73 +394,41 @@ esp_new_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m)
return ENOBUFS;
}
- bzero(buffer, auth_keylen < blocklen ? blocklen : auth_keylen);
+ bzero(buffer, txd.edx_authkeylen < blocklen ?
+ blocklen : txd.edx_authkeylen);
/* Copy the key to the buffer */
m_copydata(m, EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN + xd->edx_ivlen +
- enc_keylen, auth_keylen, buffer);
+ txd.edx_confkeylen, txd.edx_authkeylen, buffer);
/* Shorten the key if necessary */
- if (auth_keylen > blocklen)
+ if (txd.edx_authkeylen > blocklen)
{
- switch (xd->edx_hash_algorithm)
- {
- case ALG_AUTH_MD5:
- MD5Init(&(xd->edx_md5_ictx));
- MD5Update(&(xd->edx_md5_ictx), buffer, auth_keylen);
- bzero(buffer,
- auth_keylen < blocklen ? blocklen : auth_keylen);
- MD5Final(buffer, &(xd->edx_md5_ictx));
- break;
-
- case ALG_AUTH_SHA1:
- SHA1Init(&(xd->edx_sha1_ictx));
- SHA1Update(&(xd->edx_sha1_ictx), buffer, auth_keylen);
- bzero(buffer,
- auth_keylen < blocklen ? blocklen : auth_keylen);
- SHA1Final(buffer, &(xd->edx_sha1_ictx));
- break;
- }
+ xd->edx_hash->Init(&(xd->edx_ictx));
+ xd->edx_hash->Update(&(xd->edx_ictx), buffer, txd.edx_authkeylen);
+ bzero(buffer, txd.edx_authkeylen < blocklen ?
+ blocklen : txd.edx_authkeylen);
+ xd->edx_hash->Final(buffer, &(xd->edx_ictx));
}
/* Precompute the I and O pads of the HMAC */
for (i = 0; i < blocklen; i++)
buffer[i] ^= HMAC_IPAD_VAL;
- switch (xd->edx_hash_algorithm)
- {
- case ALG_AUTH_MD5:
- MD5Init(&(xd->edx_md5_ictx));
- MD5Update(&(xd->edx_md5_ictx), buffer, blocklen);
- break;
-
- case ALG_AUTH_SHA1:
- SHA1Init(&(xd->edx_sha1_ictx));
- SHA1Update(&(xd->edx_sha1_ictx), buffer, blocklen);
- break;
- }
+ xd->edx_hash->Init(&(xd->edx_ictx));
+ xd->edx_hash->Update(&(xd->edx_ictx), buffer, blocklen);
for (i = 0; i < blocklen; i++)
buffer[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
- switch (xd->edx_hash_algorithm)
- {
- case ALG_AUTH_MD5:
- MD5Init(&(xd->edx_md5_octx));
- MD5Update(&(xd->edx_md5_octx), buffer, blocklen);
- break;
-
- case ALG_AUTH_SHA1:
- SHA1Init(&(xd->edx_sha1_octx));
- SHA1Update(&(xd->edx_sha1_octx), buffer, blocklen);
- break;
- }
+ xd->edx_hash->Init(&(xd->edx_octx));
+ xd->edx_hash->Update(&(xd->edx_octx), buffer, blocklen);
bzero(buffer, blocklen);
free(buffer, M_TEMP);
}
- bzero(rk, 6 * sizeof(u_int32_t)); /* paranoid */
+ bzero(rk, 14 * sizeof(u_int32_t)); /* paranoid */
bzero(ipseczeroes, IPSEC_ZEROES_SIZE); /* paranoid */
return 0;
@@ -372,7 +451,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
{
struct esp_new_xdata *xd;
struct ip *ip, ipo;
- u_char iv[ESP_3DES_IVS], niv[ESP_3DES_IVS], blk[ESP_3DES_BLKS], opts[40];
+ u_char iv[ESP_MAX_IVS], niv[ESP_MAX_IVS], blk[ESP_MAX_BLKS], opts[40];
u_char *idat, *odat;
struct esp_new *esp;
struct ifnet *rcvif;
@@ -380,47 +459,18 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
int count, off, errc;
u_int32_t btsx;
struct mbuf *mi, *mo;
- MD5_CTX md5ctx;
- SHA1_CTX sha1ctx;
+ union {
+ MD5_CTX md5ctx;
+ SHA1_CTX sha1ctx;
+ } ctx;
u_char buf[AH_ALEN_MAX], buf2[AH_ALEN_MAX];
xd = (struct esp_new_xdata *)tdb->tdb_xdata;
- switch (xd->edx_enc_algorithm)
- {
- case ALG_ENC_DES:
- blks = ESP_DES_BLKS;
- break;
-
- case ALG_ENC_3DES:
- blks = ESP_3DES_BLKS;
- break;
-
- default:
- if (encdebug)
- log(LOG_ALERT,
- "esp_new_input(): unsupported algorithm %d in SA %x/%08x\n",
- xd->edx_enc_algorithm, tdb->tdb_dst, ntohl(tdb->tdb_spi));
- m_freem(m);
- return NULL;
- }
+ blks = xd->edx_xform->blocksize;
if (xd->edx_flags & ESP_NEW_FLAG_AUTH)
- {
- switch (xd->edx_hash_algorithm)
- {
- case ALG_AUTH_MD5:
- case ALG_AUTH_SHA1:
- alen = AH_HMAC_HASHLEN;
- break;
-
- default:
- if (encdebug)
- log(LOG_ALERT, "esp_new_input(): unsupported algorithm %d in SA %x/%08x\n", xd->edx_hash_algorithm, tdb->tdb_dst, ntohl(tdb->tdb_spi));
- m_freem(m);
- return NULL;
- }
- }
+ alen = AH_HMAC_HASHLEN;
else
alen = 0;
@@ -514,16 +564,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
if (xd->edx_flags & ESP_NEW_FLAG_AUTH)
{
- switch (xd->edx_hash_algorithm)
- {
- case ALG_AUTH_MD5:
- md5ctx = xd->edx_md5_ictx;
- break;
-
- case ALG_AUTH_SHA1:
- sha1ctx = xd->edx_sha1_ictx;
- break;
- }
+ bcopy(&(xd->edx_ictx), &ctx, xd->edx_hash->ctxsize);
/* Auth covers SPI + SN + IV*/
oplen = plen + 2 * sizeof(u_int32_t) + xd->edx_ivlen;
@@ -537,19 +578,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
count = min(mo->m_len - off, oplen);
- switch (xd->edx_hash_algorithm)
- {
- case ALG_AUTH_MD5:
- MD5Update(&md5ctx, mtod(mo, unsigned char *) + off,
- count);
- break;
-
- case ALG_AUTH_SHA1:
- SHA1Update(&sha1ctx, mtod(mo, unsigned char *) + off,
- count);
- break;
- }
-
+ xd->edx_hash->Update(&ctx, mtod(mo, unsigned char *) + off, count);
oplen -= count;
if (oplen == 0)
{
@@ -581,22 +610,10 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
mo = mo->m_next;
}
- switch (xd->edx_hash_algorithm)
- {
- case ALG_AUTH_MD5:
- MD5Final(buf2, &md5ctx);
- md5ctx = xd->edx_md5_octx;
- MD5Update(&md5ctx, buf2, AH_MD5_ALEN);
- MD5Final(buf2, &md5ctx);
- break;
-
- case ALG_AUTH_SHA1:
- SHA1Final(buf2, &sha1ctx);
- sha1ctx = xd->edx_sha1_octx;
- SHA1Update(&sha1ctx, buf2, AH_SHA1_ALEN);
- SHA1Final(buf2, &sha1ctx);
- break;
- }
+ xd->edx_hash->Final(buf2, &ctx);
+ bcopy(&(xd->edx_octx), &ctx, xd->edx_hash->ctxsize);
+ xd->edx_hash->Update(&ctx, buf2, xd->edx_hash->hashsize);
+ xd->edx_hash->Final(buf2, &ctx);
if (bcmp(buf2, buf, AH_HMAC_HASHLEN))
{
@@ -668,18 +685,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb)
if (i == blks)
{
- switch (xd->edx_enc_algorithm)
- {
- case ALG_ENC_DES:
- des_ecb_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]), 0);
- break;
-
- case ALG_ENC_3DES:
- des_ecb3_encrypt(blk, blk, (caddr_t) (xd->edx_eks[2]),
- (caddr_t) (xd->edx_eks[1]),
- (caddr_t) (xd->edx_eks[0]), 0);
- break;
- }
+ xd->edx_xform->decrypt(xd, blk);
for (i=0; i<8; i++)
{
@@ -841,51 +847,24 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
struct mbuf *mi, *mo;
u_char *pad, *idat, *odat;
u_char iv[ESP_3DES_IVS], blk[ESP_3DES_IVS], auth[AH_ALEN_MAX], opts[40];
- MD5_CTX md5ctx;
- SHA1_CTX sha1ctx;
+ union {
+ MD5_CTX md5ctx;
+ SHA1_CTX sha1ctx;
+ } ctx;
int iphlen, blks, alen;
xd = (struct esp_new_xdata *) tdb->tdb_xdata;
- switch (xd->edx_enc_algorithm)
- {
- case ALG_ENC_DES:
- blks = ESP_DES_BLKS;
- break;
-
- case ALG_ENC_3DES:
- blks = ESP_3DES_BLKS;
- break;
-
- default:
- if (encdebug)
- log(LOG_ALERT,
- "esp_new_output(): unsupported algorithm %d in SA %x/%08x\n",
- xd->edx_enc_algorithm, tdb->tdb_dst, ntohl(tdb->tdb_spi));
- m_freem(m);
- return NULL;
- }
+ blks = xd->edx_xform->blocksize;
if (xd->edx_flags & ESP_NEW_FLAG_AUTH)
{
- switch (xd->edx_hash_algorithm)
- {
- case ALG_AUTH_MD5:
- case ALG_AUTH_SHA1:
- alen = AH_HMAC_HASHLEN;
+ alen = AH_HMAC_HASHLEN;
#ifdef ENCDEBUG
- if (encdebug)
- printf("esp_new_output(): using hash algorithm %d\n",
- xd->edx_hash_algorithm);
+ if (encdebug)
+ printf("esp_new_output(): using hash algorithm: %s\n",
+ xd->edx_hash->name);
#endif /* ENCDEBUG */
- break;
-
- default:
- if (encdebug)
- log(LOG_ALERT, "esp_new_output(): unsupported algorithm %d in SA %x/%08x\n", xd->edx_hash_algorithm, tdb->tdb_dst, ntohl(tdb->tdb_spi));
- m_freem(m);
- return NULL;
- }
}
else
alen = 0;
@@ -997,20 +976,9 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
/* Authenticate the esp header */
if (xd->edx_flags & ESP_NEW_FLAG_AUTH)
{
- switch (xd->edx_hash_algorithm)
- {
- case ALG_AUTH_MD5:
- md5ctx = xd->edx_md5_ictx;
- MD5Update(&md5ctx, (unsigned char *) &espo,
- 2 * sizeof(u_int32_t) + xd->edx_ivlen);
- break;
-
- case ALG_AUTH_SHA1:
- sha1ctx = xd->edx_sha1_ictx;
- SHA1Update(&sha1ctx, (unsigned char *) &espo,
- 2 * sizeof(u_int32_t) + xd->edx_ivlen);
- break;
- }
+ bcopy(&(xd->edx_ictx), &ctx, xd->edx_hash->ctxsize);
+ xd->edx_hash->Update(&ctx, (unsigned char *) &espo,
+ 2 * sizeof(u_int32_t) + xd->edx_ivlen);
}
/* Encrypt the payload */
@@ -1034,30 +1002,10 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
if (i == blks)
{
- switch (xd->edx_enc_algorithm)
- {
- case ALG_ENC_DES:
- des_ecb_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]), 1);
- break;
-
- case ALG_ENC_3DES:
- des_ecb3_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]),
- (caddr_t) (xd->edx_eks[1]),
- (caddr_t) (xd->edx_eks[2]), 1);
- break;
- }
+ xd->edx_xform->encrypt(xd, blk);
if (xd->edx_flags & ESP_NEW_FLAG_AUTH)
- switch (xd->edx_hash_algorithm)
- {
- case ALG_AUTH_MD5:
- MD5Update(&md5ctx, blk, blks);
- break;
-
- case ALG_AUTH_SHA1:
- SHA1Update(&sha1ctx, blk, blks);
- break;
- }
+ xd->edx_hash->Update(&ctx, blk, blks);
for (i = 0; i < blks; i++)
{
@@ -1084,22 +1032,10 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb,
/* Put in authentication data */
if (xd->edx_flags & ESP_NEW_FLAG_AUTH)
{
- switch (xd->edx_hash_algorithm)
- {
- case ALG_AUTH_MD5:
- MD5Final(auth, &md5ctx);
- md5ctx = xd->edx_md5_octx;
- MD5Update(&md5ctx, auth, AH_MD5_ALEN);
- MD5Final(auth, &md5ctx);
- break;
-
- case ALG_AUTH_SHA1:
- SHA1Final(auth, &sha1ctx);
- sha1ctx = xd->edx_sha1_octx;
- SHA1Update(&sha1ctx, auth, AH_SHA1_ALEN);
- SHA1Final(auth, &sha1ctx);
- break;
- }
+ xd->edx_hash->Final(auth, &ctx);
+ bcopy(&(xd->edx_octx), &ctx, xd->edx_hash->ctxsize);
+ xd->edx_hash->Update(&ctx, auth, xd->edx_hash->hashsize);
+ xd->edx_hash->Final(auth, &ctx);
/* Copy the final authenticator */
bcopy(auth, pad + padding, alen);