Skip to content

Commit

Permalink
Add support for the Extended (64-bit) Sequence Number as defined
Browse files Browse the repository at this point in the history
in RFC4302 and RFC4303.  Right now only software crypto engine is
capable of doing it.

Replay check was rewritten to implement algorithm described in the
Appendix A of RFC4303 and the window size was increased to 64.

Tested against OpenBSD, Linux (strongswan) and Windows.

No objection from the usual suspects.
  • Loading branch information
mbelop committed Jun 29, 2012
1 parent 57bb770 commit 6b4cbaf
Show file tree
Hide file tree
Showing 9 changed files with 237 additions and 86 deletions.
14 changes: 11 additions & 3 deletions sys/crypto/cryptodev.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: cryptodev.h,v 1.55 2010/12/16 16:56:08 jsg Exp $ */
/* $OpenBSD: cryptodev.h,v 1.56 2012/06/29 14:48:04 mikeb Exp $ */

/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
Expand Down Expand Up @@ -108,7 +108,8 @@
#define CRYPTO_AES_192_GMAC 25
#define CRYPTO_AES_256_GMAC 26
#define CRYPTO_AES_GMAC 27
#define CRYPTO_ALGORITHM_MAX 27 /* Keep updated */
#define CRYPTO_ESN 28 /* Support for Extended Sequence Numbers */
#define CRYPTO_ALGORITHM_MAX 28 /* Keep updated */

/* Algorithm flags */
#define CRYPTO_ALG_FLAG_SUPPORTED 0x01 /* Algorithm is supported */
Expand All @@ -121,7 +122,12 @@ struct cryptoini {
int cri_klen; /* Key length, in bits */
int cri_rnd; /* Algorithm rounds, where relevant */
caddr_t cri_key; /* key to use */
u_int8_t cri_iv[EALG_MAX_BLOCK_LEN]; /* IV to use */
union {
u_int8_t iv[EALG_MAX_BLOCK_LEN]; /* IV to use */
u_int8_t esn[4]; /* high-order ESN */
} u;
#define cri_iv u.iv
#define cri_esn u.esn
struct cryptoini *cri_next;
};

Expand All @@ -138,8 +144,10 @@ struct cryptodesc {
#define CRD_F_IV_EXPLICIT 0x04 /* IV explicitly provided */
#define CRD_F_DSA_SHA_NEEDED 0x08 /* Compute SHA-1 of buffer for DSA */
#define CRD_F_COMP 0x10 /* Set when doing compression */
#define CRD_F_ESN 0x20 /* Set when ESN field is provided */

struct cryptoini CRD_INI; /* Initialization/context data */
#define crd_esn CRD_INI.cri_esn
#define crd_iv CRD_INI.cri_iv
#define crd_key CRD_INI.cri_key
#define crd_rnd CRD_INI.cri_rnd
Expand Down
31 changes: 25 additions & 6 deletions sys/crypto/cryptosoft.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: cryptosoft.c,v 1.63 2011/01/11 23:00:21 markus Exp $ */
/* $OpenBSD: cryptosoft.c,v 1.64 2012/06/29 14:48:04 mikeb Exp $ */

/*
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
Expand Down Expand Up @@ -446,6 +446,9 @@ swcr_authcompute(struct cryptop *crp, struct cryptodesc *crd,
if (err)
return err;

if (crd->crd_flags & CRD_F_ESN)
axf->Update(&ctx, crd->crd_esn, 4);

switch (sw->sw_alg) {
case CRYPTO_MD5_HMAC:
case CRYPTO_SHA1_HMAC:
Expand Down Expand Up @@ -505,7 +508,7 @@ swcr_combined(struct cryptop *crp)
struct uio *uio = NULL;
caddr_t buf = (caddr_t)crp->crp_buf;
uint32_t *blkp;
int i, blksz, ivlen, outtype, len;
int aadlen, blksz, i, ivlen, outtype, left, len;

for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
for (sw = swcr_sessions[crp->crp_sid & 0xffffffff];
Expand Down Expand Up @@ -576,10 +579,22 @@ swcr_combined(struct cryptop *crp)
axf->Reinit(&ctx, iv, ivlen);

/* Supply MAC with AAD */
for (i = 0; i < crda->crd_len; i += blksz) {
len = MIN(crda->crd_len - i, blksz);
COPYDATA(outtype, buf, crda->crd_skip + i, len, blk);
axf->Update(&ctx, blk, len);
aadlen = crda->crd_len;
if (crda->crd_flags & CRD_F_ESN)
aadlen += 4;
for (i = 0; i < aadlen; i += blksz) {
len = 0;
if (i < crda->crd_len) {
len = MIN(crda->crd_len - i, blksz);
COPYDATA(outtype, buf, crda->crd_skip + i, len, blk);
}
left = blksz - len;
if (crda->crd_flags & CRD_F_ESN && left > 0) {
bcopy(crda->crd_esn, blk + len, MIN(left, aadlen - i));
len += MIN(left, aadlen - i);
}
bzero(blk + len, blksz - len);
axf->Update(&ctx, blk, blksz);
}

if (exf->reinit)
Expand Down Expand Up @@ -937,6 +952,9 @@ swcr_newsession(u_int32_t *sid, struct cryptoini *cri)
cxf = &comp_algo_deflate;
(*swd)->sw_cxf = cxf;
break;
case CRYPTO_ESN:
/* nothing to do */
break;
default:
swcr_freesession(i);
return EINVAL;
Expand Down Expand Up @@ -1192,6 +1210,7 @@ swcr_init(void)
algs[CRYPTO_AES_128_GMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_AES_192_GMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_AES_256_GMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_ESN] = CRYPTO_ALG_FLAG_SUPPORTED;

crypto_register(swcr_id, algs, swcr_newsession,
swcr_freesession, swcr_process);
Expand Down
4 changes: 2 additions & 2 deletions sys/net/if_pfsync.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: if_pfsync.h,v 1.44 2010/11/29 05:31:38 dlg Exp $ */
/* $OpenBSD: if_pfsync.h,v 1.45 2012/06/29 14:48:04 mikeb Exp $ */

/*
* Copyright (c) 2001 Michael Shalayeff
Expand Down Expand Up @@ -212,7 +212,7 @@ struct pfsync_bus {
struct pfsync_tdb {
u_int32_t spi;
union sockaddr_union dst;
u_int32_t rpl;
u_int64_t rpl;
u_int64_t cur_bytes;
u_int8_t sproto;
u_int8_t updates;
Expand Down
19 changes: 10 additions & 9 deletions sys/net/pfkeyv2.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: pfkeyv2.h,v 1.60 2010/10/06 22:19:20 mikeb Exp $ */
/* $OpenBSD: pfkeyv2.h,v 1.61 2012/06/29 14:48:04 mikeb Exp $ */
/*
* @(#)COPYRIGHT 1.1 (NRL) January 1998
*
Expand Down Expand Up @@ -330,15 +330,16 @@ struct sadb_x_tap {
#define SADB_X_CALG_LZS 3
#define SADB_X_CALG_MAX 3

#define SADB_SAFLAGS_PFS 0x001 /* perfect forward secrecy */
#define SADB_X_SAFLAGS_HALFIV 0x002 /* Used for ESP-old */
#define SADB_X_SAFLAGS_TUNNEL 0x004 /* Force tunneling */
#define SADB_X_SAFLAGS_CHAINDEL 0x008 /* Delete whole SA chain */
#define SADB_X_SAFLAGS_RANDOMPADDING 0x080 /* Random ESP padding */
#define SADB_X_SAFLAGS_NOREPLAY 0x100 /* No replay counter */
#define SADB_X_SAFLAGS_UDPENCAP 0x200 /* ESP in UDP */
#define SADB_SAFLAGS_PFS 0x001 /* perfect forward secrecy */
#define SADB_X_SAFLAGS_HALFIV 0x002 /* Used for ESP-old */
#define SADB_X_SAFLAGS_TUNNEL 0x004 /* Force tunneling */
#define SADB_X_SAFLAGS_CHAINDEL 0x008 /* Delete whole SA chain */
#define SADB_X_SAFLAGS_RANDOMPADDING 0x080 /* Random ESP padding */
#define SADB_X_SAFLAGS_NOREPLAY 0x100 /* No replay counter */
#define SADB_X_SAFLAGS_UDPENCAP 0x200 /* ESP in UDP */
#define SADB_X_SAFLAGS_ESN 0x400 /* Extended Sequence Number */

#define SADB_X_POLICYFLAGS_POLICY 0x0001 /* This is a static policy */
#define SADB_X_POLICYFLAGS_POLICY 0x0001 /* This is a static policy */

#define SADB_IDENTTYPE_RESERVED 0
#define SADB_IDENTTYPE_PREFIX 1
Expand Down
8 changes: 7 additions & 1 deletion sys/net/pfkeyv2_convert.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: pfkeyv2_convert.c,v 1.35 2011/04/13 11:28:47 markus Exp $ */
/* $OpenBSD: pfkeyv2_convert.c,v 1.36 2012/06/29 14:48:04 mikeb Exp $ */
/*
* The author of this code is Angelos D. Keromytis (angelos@keromytis.org)
*
Expand Down Expand Up @@ -149,6 +149,9 @@ import_sa(struct tdb *tdb, struct sadb_sa *sadb_sa, struct ipsecinit *ii)

if (sadb_sa->sadb_sa_flags & SADB_X_SAFLAGS_UDPENCAP)
tdb->tdb_flags |= TDBF_UDPENCAP;

if (sadb_sa->sadb_sa_flags & SADB_X_SAFLAGS_ESN)
tdb->tdb_flags |= TDBF_ESN;
}

if (sadb_sa->sadb_sa_state != SADB_SASTATE_MATURE)
Expand Down Expand Up @@ -292,6 +295,9 @@ export_sa(void **p, struct tdb *tdb)
if (tdb->tdb_flags & TDBF_UDPENCAP)
sadb_sa->sadb_sa_flags |= SADB_X_SAFLAGS_UDPENCAP;

if (tdb->tdb_flags & TDBF_ESN)
sadb_sa->sadb_sa_flags |= SADB_X_SAFLAGS_ESN;

*p += sizeof(struct sadb_sa);
}

Expand Down
4 changes: 2 additions & 2 deletions sys/net/pfkeyv2_parsemessage.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: pfkeyv2_parsemessage.c,v 1.45 2012/03/28 19:43:21 claudio Exp $ */
/* $OpenBSD: pfkeyv2_parsemessage.c,v 1.46 2012/06/29 14:48:04 mikeb Exp $ */

/*
* @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
Expand Down Expand Up @@ -430,7 +430,7 @@ pfkeyv2_parsemessage(void *p, int len, void **headers)
return (EINVAL);
}

if (sadb_sa->sadb_sa_replay > 32) {
if (sadb_sa->sadb_sa_replay > 64) {
DPRINTF(("pfkeyv2_parsemessage: unsupported "
"replay window size %d in SA extension "
"header %d\n", sadb_sa->sadb_sa_replay,
Expand Down
50 changes: 37 additions & 13 deletions sys/netinet/ip_ah.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* $OpenBSD: ip_ah.c,v 1.99 2011/01/11 15:42:05 deraadt Exp $ */
/* $OpenBSD: ip_ah.c,v 1.100 2012/06/29 14:48:04 mikeb Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
Expand Down Expand Up @@ -99,7 +99,7 @@ int
ah_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
{
struct auth_hash *thash = NULL;
struct cryptoini cria;
struct cryptoini cria, crin;

/* Authentication operation. */
switch (ii->ii_authalg) {
Expand Down Expand Up @@ -166,6 +166,13 @@ ah_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
cria.cri_klen = ii->ii_authkeylen * 8;
cria.cri_key = ii->ii_authkey;

if ((tdbp->tdb_wnd > 0) && !(tdbp->tdb_flags & TDBF_NOREPLAY) &&
(tdbp->tdb_flags & TDBF_ESN)) {
bzero(&crin, sizeof(crin));
crin.cri_alg = CRYPTO_ESN;
cria.cri_next = &crin;
}

return crypto_newsession(&tdbp->tdb_cryptoid, &cria, 0);
}

Expand Down Expand Up @@ -543,7 +550,7 @@ ah_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
struct tdb_crypto *tc;
struct m_tag *mtag;
u_int32_t btsx;
u_int32_t btsx, esn;
u_int8_t hl;
int rplen;

Expand All @@ -565,8 +572,8 @@ ah_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
sizeof(u_int32_t), (caddr_t) &btsx);
btsx = ntohl(btsx);

switch (checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl),
tdb->tdb_wnd, &(tdb->tdb_bitmap), 0)) {
switch (checkreplaywindow(btsx, &tdb->tdb_rpl, tdb->tdb_wnd,
&tdb->tdb_bitmap, &esn, tdb->tdb_flags & TDBF_ESN, 0)) {
case 0: /* All's well. */
break;

Expand All @@ -585,15 +592,15 @@ ah_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
"SA %s/%08x\n", ipsp_address(tdb->tdb_dst),
ntohl(tdb->tdb_spi)));

ahstat.ahs_replay++;
m_freem(m);
return ENOBUFS;

default:
DPRINTF(("ah_input(): bogus value from "
"checkreplaywindow32() in SA %s/%08x\n",
"checkreplaywindow() in SA %s/%08x\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));

ahstat.ahs_replay++;
m_freem(m);
return ENOBUFS;
}
Expand Down Expand Up @@ -652,6 +659,13 @@ ah_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
crda->crd_key = tdb->tdb_amxkey;
crda->crd_klen = tdb->tdb_amxkeylen * 8;

if ((tdb->tdb_wnd > 0) && !(tdb->tdb_flags & TDBF_NOREPLAY) &&
(tdb->tdb_flags & TDBF_ESN)) {
esn = htonl(esn);
bcopy(&esn, crda->crd_esn, 4);
crda->crd_flags |= CRD_F_ESN;
}

#ifdef notyet
/* Find out if we've already done crypto. */
for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL);
Expand Down Expand Up @@ -745,7 +759,7 @@ ah_input_cb(void *op)
struct cryptop *crp;
struct m_tag *mtag;
struct tdb *tdb;
u_int32_t btsx;
u_int32_t btsx, esn;
u_int8_t prot;
caddr_t ptr;

Expand Down Expand Up @@ -846,8 +860,8 @@ ah_input_cb(void *op)
sizeof(u_int32_t), (caddr_t) &btsx);
btsx = ntohl(btsx);

switch (checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl),
tdb->tdb_wnd, &(tdb->tdb_bitmap), 1)) {
switch (checkreplaywindow(btsx, &tdb->tdb_rpl, tdb->tdb_wnd,
&tdb->tdb_bitmap, &esn, tdb->tdb_flags & TDBF_ESN, 1)) {
case 0: /* All's well. */
#if NPFSYNC > 0
pfsync_update_tdb(tdb,0);
Expand All @@ -869,15 +883,15 @@ ah_input_cb(void *op)
"SA %s/%08x\n", ipsp_address(tdb->tdb_dst),
ntohl(tdb->tdb_spi)));

ahstat.ahs_replay++;
error = ENOBUFS;
goto baddone;

default:
DPRINTF(("ah_input_cb(): bogus value from "
"checkreplaywindow32() in SA %s/%08x\n",
"checkreplaywindow() in SA %s/%08x\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));

ahstat.ahs_replay++;
error = ENOBUFS;
goto baddone;
}
Expand Down Expand Up @@ -1144,7 +1158,8 @@ ah_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
m_copyback(m, skip + rplen, ahx->authsize, ipseczeroes, M_NOWAIT);

if (!(tdb->tdb_flags & TDBF_NOREPLAY)) {
ah->ah_rpl = htonl(tdb->tdb_rpl++);
tdb->tdb_rpl++;
ah->ah_rpl = htonl((u_int32_t)(tdb->tdb_rpl & 0xffffffff));
#if NPFSYNC > 0
pfsync_update_tdb(tdb,1);
#endif
Expand All @@ -1171,6 +1186,15 @@ ah_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
crda->crd_key = tdb->tdb_amxkey;
crda->crd_klen = tdb->tdb_amxkeylen * 8;

if ((tdb->tdb_wnd > 0) && !(tdb->tdb_flags & TDBF_NOREPLAY) &&
(tdb->tdb_flags & TDBF_ESN)) {
u_int32_t esn;

esn = htonl((u_int32_t)(tdb->tdb_rpl >> 32));
bcopy(&esn, crda->crd_esn, 4);
crda->crd_flags |= CRD_F_ESN;
}

/* Allocate IPsec-specific opaque crypto info. */
if ((tdb->tdb_flags & TDBF_SKIPCRYPTO) == 0)
tc = malloc(sizeof(*tc) + skip, M_XDATA, M_NOWAIT | M_ZERO);
Expand Down
Loading

0 comments on commit 6b4cbaf

Please sign in to comment.