diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/ubsec.c | 225 | ||||
-rw-r--r-- | sys/dev/pci/ubsecreg.h | 5 | ||||
-rw-r--r-- | sys/dev/pci/ubsecvar.h | 13 |
3 files changed, 166 insertions, 77 deletions
diff --git a/sys/dev/pci/ubsec.c b/sys/dev/pci/ubsec.c index 44cbf954117..0e569c43e3e 100644 --- a/sys/dev/pci/ubsec.c +++ b/sys/dev/pci/ubsec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ubsec.c,v 1.22 2000/08/13 21:58:06 deraadt Exp $ */ +/* $OpenBSD: ubsec.c,v 1.23 2000/08/13 22:03:09 deraadt Exp $ */ /* * Copyright (c) 2000 Jason L. Wright (jason@thought.net) @@ -358,16 +358,17 @@ feed1: * Allocate a new 'session' and return an encoded session id. 'sidp' * contains our registration id, and should contain an encoded session * id on successful allocation. - * XXX No allocation actually done here, all sessions are the same. */ int ubsec_newsession(sidp, cri) u_int32_t *sidp; struct cryptoini *cri; { - struct cryptoini *c; + struct cryptoini *c, *encini = NULL, *macini = NULL; struct ubsec_softc *sc = NULL; - char mac = 0, cry = 0; + struct ubsec_session *ses; + MD5_CTX md5ctx; + SHA1_CTX sha1ctx; int i; if (sidp == NULL || cri == NULL) @@ -384,33 +385,141 @@ ubsec_newsession(sidp, cri) for (c = cri; c != NULL; c = c->cri_next) { if (c->cri_alg == CRYPTO_MD5_HMAC96 || c->cri_alg == CRYPTO_SHA1_HMAC96) { - if (mac) + if (macini) return (EINVAL); - mac = 1; + macini = c; } else if (c->cri_alg == CRYPTO_DES_CBC || c->cri_alg == CRYPTO_3DES_CBC) { - if (cry) + if (encini) return (EINVAL); - cry = 1; + encini = c; } else return (EINVAL); } - if (mac == 0 && cry == 0) + if (encini == NULL && macini == NULL) return (EINVAL); - *sidp = UBSEC_SID(sc->sc_dv.dv_unit, 0); + if (sc->sc_sessions == NULL) { + ses = sc->sc_sessions = (struct ubsec_session *)malloc( + sizeof(struct ubsec_session), M_DEVBUF, M_NOWAIT); + if (ses == NULL) + return (ENOMEM); + i = 0; + sc->sc_nsessions = 1; + } else { + for (i = 0; i < sc->sc_nsessions; i++) { + if (sc->sc_sessions[i].ses_used == 0) { + ses = &sc->sc_sessions[i]; + break; + } + } + + if (ses == NULL) { + ses = (struct ubsec_session *)malloc( + (sc->sc_nsessions + 1) * + sizeof(struct ubsec_session), M_DEVBUF, M_NOWAIT); + if (ses == NULL) + return (ENOMEM); + for (i = 0; i < sc->sc_nsessions; i++) { + bcopy(&sc->sc_sessions[i], &ses[i], + sizeof(struct ubsec_session)); + bzero(&sc->sc_sessions[i], + sizeof(struct ubsec_session)); + } + free(sc->sc_sessions, M_DEVBUF); + sc->sc_sessions = ses; + ses = &sc->sc_sessions[sc->sc_nsessions]; + sc->sc_nsessions++; + } + } + + bzero(ses, sizeof(struct ubsec_session)); + ses->ses_used = 1; + if (encini) { + /* get an IV, network byte order */ + get_random_bytes(ses->ses_iv, sizeof(ses->ses_iv)); + + /* Go ahead and compute key in ubsec's byte order */ + if (encini->cri_alg == CRYPTO_DES_CBC) { + bcopy(encini->cri_key, &ses->ses_deskey[0], 8); + bcopy(encini->cri_key, &ses->ses_deskey[2], 8); + bcopy(encini->cri_key, &ses->ses_deskey[4], 8); + } + else + bcopy(encini->cri_key, &ses->ses_deskey[0], 24); + SWAP32(ses->ses_deskey[0]); + SWAP32(ses->ses_deskey[1]); + SWAP32(ses->ses_deskey[2]); + SWAP32(ses->ses_deskey[3]); + SWAP32(ses->ses_deskey[4]); + SWAP32(ses->ses_deskey[5]); + } + if (macini) { + if (macini->cri_alg == CRYPTO_MD5_HMAC96) { + MD5Init(&md5ctx); + MD5Update(&md5ctx, macini->cri_key, + macini->cri_klen / 8); + MD5Update(&md5ctx, hmac_ipad_buffer, + HMAC_BLOCK_LEN - (macini->cri_klen / 8)); + bcopy(md5ctx.state, ses->ses_hminner, + sizeof(md5ctx.state)); + } else { + SHA1Init(&sha1ctx); + SHA1Update(&sha1ctx, macini->cri_key, + macini->cri_klen / 8); + SHA1Update(&sha1ctx, hmac_ipad_buffer, + HMAC_BLOCK_LEN - (macini->cri_klen / 8)); + bcopy(sha1ctx.state, ses->ses_hminner, + sizeof(sha1ctx.state)); + } + + for (i = 0; i < macini->cri_klen / 8; i++) + macini->cri_key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); + + if (macini->cri_alg == CRYPTO_MD5_HMAC96) { + MD5Init(&md5ctx); + MD5Update(&md5ctx, macini->cri_key, + macini->cri_klen / 8); + MD5Update(&md5ctx, hmac_opad_buffer, + HMAC_BLOCK_LEN - (macini->cri_klen / 8)); + bcopy(md5ctx.state, ses->ses_hmouter, + sizeof(md5ctx.state)); + } else { + SHA1Init(&sha1ctx); + SHA1Update(&sha1ctx, macini->cri_key, + macini->cri_klen / 8); + SHA1Update(&sha1ctx, hmac_opad_buffer, + HMAC_BLOCK_LEN - (macini->cri_klen / 8)); + bcopy(sha1ctx.state, ses->ses_hmouter, + sizeof(sha1ctx.state)); + } + + for (i = 0; i < macini->cri_klen / 8; i++) + macini->cri_key[i] ^= HMAC_OPAD_VAL; + } + + *sidp = UBSEC_SID(sc->sc_dv.dv_unit, i); return (0); } /* * Deallocate a session. - * XXX Nothing to do yet. */ int -ubsec_freesession(sid) - u_int64_t sid; +ubsec_freesession(tid) + u_int64_t tid; { + struct ubsec_softc *sc; + int card, session; + u_int32_t sid = ((u_int32_t) tid) & 0xffffffff; + + card = UBSEC_CARD(sid); + if (card >= ubsec_cd.cd_ndevs || ubsec_cd.cd_devs[card] == NULL) + return (EINVAL); + sc = ubsec_cd.cd_devs[card]; + session = UBSEC_SESSION(sid); + bzero(&sc->sc_sessions[session], sizeof(sc->sc_sessions[session])); return (0); } @@ -418,14 +527,13 @@ int ubsec_process(crp) struct cryptop *crp; { - MD5_CTX md5ctx; - SHA1_CTX sha1ctx; struct ubsec_q *q = NULL; int card, err, i, j, s, nicealign; struct ubsec_softc *sc; struct cryptodesc *crd1, *crd2, *maccrd, *enccrd; int encoffset = 0, macoffset = 0, sskip, dskip, stheend, dtheend; int16_t coffset; + struct ubsec_session *ses; if (crp == NULL || crp->crp_callback == NULL) return (EINVAL); @@ -454,6 +562,8 @@ ubsec_process(crp) } bzero(q, sizeof(struct ubsec_q)); + ses = q->q_ses = &sc->sc_sessions[UBSEC_SESSION(crp->crp_sid)]; + q->q_mcr = (struct ubsec_mcr *)malloc(sizeof(struct ubsec_mcr), M_DEVBUF, M_NOWAIT); if (q->q_mcr == NULL) { @@ -529,7 +639,7 @@ ubsec_process(crp) if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) bcopy(enccrd->crd_iv, &q->q_ctx.pc_iv[0], 8); else - get_random_bytes(&q->q_ctx.pc_iv[0], 8); + bcopy(&ses->ses_iv[0], &q->q_ctx.pc_iv[0], 8); m_copyback(q->q_src_m, enccrd->crd_inject, 8, (caddr_t)&q->q_ctx.pc_iv); @@ -547,73 +657,26 @@ ubsec_process(crp) 8, (caddr_t)&q->q_ctx.pc_iv[0]); } - if (enccrd->crd_alg == CRYPTO_DES_CBC) { - /* Cheat: des == 3des with two of the keys the same */ - bcopy(enccrd->crd_key, &q->q_ctx.pc_deskey[0], 8); - bcopy(enccrd->crd_key, &q->q_ctx.pc_deskey[2], 8); - bcopy(enccrd->crd_key, &q->q_ctx.pc_deskey[4], 8); - } else - bcopy(enccrd->crd_key, &q->q_ctx.pc_deskey[0], 24); - + q->q_ctx.pc_deskey[0] = ses->ses_deskey[0]; + q->q_ctx.pc_deskey[1] = ses->ses_deskey[1]; + q->q_ctx.pc_deskey[2] = ses->ses_deskey[2]; + q->q_ctx.pc_deskey[3] = ses->ses_deskey[3]; + q->q_ctx.pc_deskey[4] = ses->ses_deskey[4]; + q->q_ctx.pc_deskey[5] = ses->ses_deskey[5]; SWAP32(q->q_ctx.pc_iv[0]); SWAP32(q->q_ctx.pc_iv[1]); - SWAP32(q->q_ctx.pc_deskey[0]); - SWAP32(q->q_ctx.pc_deskey[1]); - SWAP32(q->q_ctx.pc_deskey[2]); - SWAP32(q->q_ctx.pc_deskey[3]); - SWAP32(q->q_ctx.pc_deskey[4]); - SWAP32(q->q_ctx.pc_deskey[5]); } if (maccrd) { macoffset = maccrd->crd_skip; - - for (i = 0; i < maccrd->crd_klen / 8; i++) - maccrd->crd_key[i] ^= HMAC_IPAD_VAL; - - if (maccrd->crd_alg == CRYPTO_MD5_HMAC96) { + if (maccrd->crd_alg == CRYPTO_MD5_HMAC96) q->q_ctx.pc_flags |= UBS_PKTCTX_AUTH_MD5; - MD5Init(&md5ctx); - MD5Update(&md5ctx, maccrd->crd_key, - maccrd->crd_klen / 8); - MD5Update(&md5ctx, hmac_ipad_buffer, - HMAC_BLOCK_LEN - (maccrd->crd_klen / 8)); - bcopy(md5ctx.state, q->q_ctx.pc_hminner, - sizeof(md5ctx.state)); - } else { + else q->q_ctx.pc_flags |= UBS_PKTCTX_AUTH_SHA1; - SHA1Init(&sha1ctx); - SHA1Update(&sha1ctx, maccrd->crd_key, - maccrd->crd_klen / 8); - SHA1Update(&sha1ctx, hmac_ipad_buffer, - HMAC_BLOCK_LEN - (maccrd->crd_klen / 8)); - bcopy(sha1ctx.state, q->q_ctx.pc_hminner, - sizeof(sha1ctx.state)); + for (i = 0; i < 5; i++) { + q->q_ctx.pc_hminner[i] = ses->ses_hminner[i]; + q->q_ctx.pc_hmouter[i] = ses->ses_hmouter[i]; } - - for (i = 0; i < maccrd->crd_klen / 8; i++) - maccrd->crd_key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); - - if (maccrd->crd_alg == CRYPTO_MD5_HMAC96) { - MD5Init(&md5ctx); - MD5Update(&md5ctx, maccrd->crd_key, - maccrd->crd_klen / 8); - MD5Update(&md5ctx, hmac_opad_buffer, - HMAC_BLOCK_LEN - (maccrd->crd_klen / 8)); - bcopy(md5ctx.state, q->q_ctx.pc_hmouter, - sizeof(md5ctx.state)); - } else { - SHA1Init(&sha1ctx); - SHA1Update(&sha1ctx, maccrd->crd_key, - maccrd->crd_klen / 8); - SHA1Update(&sha1ctx, hmac_opad_buffer, - HMAC_BLOCK_LEN - (maccrd->crd_klen / 8)); - bcopy(sha1ctx.state, q->q_ctx.pc_hmouter, - sizeof(sha1ctx.state)); - } - - for (i = 0; i < maccrd->crd_klen / 8; i++) - maccrd->crd_key[i] ^= HMAC_OPAD_VAL; } if (enccrd && maccrd) { @@ -852,6 +915,20 @@ ubsec_callback(q) crp->crp_buf = (caddr_t)q->q_dst_m; } + /* copy out IV for future use */ + if ((q->q_ctx.pc_flags & (UBS_PKTCTX_ENC_3DES | UBS_PKTCTX_INBOUND)) == + UBS_PKTCTX_ENC_3DES) { + for (crd = crp->crp_desc; crd; crd = crd->crd_next) { + if (crd->crd_alg != CRYPTO_DES_CBC && + crd->crd_alg != CRYPTO_3DES_CBC) + continue; + m_copydata((struct mbuf *)crp->crp_buf, + crd->crd_skip + crd->crd_len - 8, 8, + (u_int8_t *)q->q_ses->ses_iv); + break; + } + } + for (crd = crp->crp_desc; crd; crd = crd->crd_next) { if (crd->crd_alg != CRYPTO_MD5_HMAC96 && crd->crd_alg != CRYPTO_SHA1_HMAC96) diff --git a/sys/dev/pci/ubsecreg.h b/sys/dev/pci/ubsecreg.h index 304c95c4c46..ba06c25298f 100644 --- a/sys/dev/pci/ubsecreg.h +++ b/sys/dev/pci/ubsecreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ubsecreg.h,v 1.5 2000/08/11 19:38:15 deraadt Exp $ */ +/* $OpenBSD: ubsecreg.h,v 1.6 2000/08/13 22:03:09 deraadt Exp $ */ /* * Copyright (c) 2000 Theo de Raadt @@ -70,7 +70,8 @@ #define BS_ERR_READ 0x00000001 /* fault was on read */ #define UBSEC_CARD(sid) (((sid) & 0xf0000000) >> 28) -#define UBSEC_SID(crd,ses) (((crd) << 28) | ((ses) & 0x7ff)) +#define UBSEC_SESSION(sid) ( (sid) & 0x0fffffff) +#define UBSEC_SID(crd,ses) (((crd) << 28) | ((ses) & 0x0fffffff)) #define MAX_SCATTER 64 struct ubsec_pktctx { diff --git a/sys/dev/pci/ubsecvar.h b/sys/dev/pci/ubsecvar.h index 7960ba26b0a..e4e22e6a8e0 100644 --- a/sys/dev/pci/ubsecvar.h +++ b/sys/dev/pci/ubsecvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ubsecvar.h,v 1.7 2000/08/11 19:38:16 deraadt Exp $ */ +/* $OpenBSD: ubsecvar.h,v 1.8 2000/08/13 22:03:09 deraadt Exp $ */ /* * Copyright (c) 2000 Theo de Raadt @@ -38,6 +38,8 @@ struct ubsec_softc { SIMPLEQ_HEAD(,ubsec_q) sc_queue; /* packet queue */ int sc_nqueue; /* count enqueued */ SIMPLEQ_HEAD(,ubsec_q) sc_qchip; /* on chip */ + int sc_nsessions; /* # of sessions */ + struct ubsec_session *sc_sessions; /* sessions */ }; struct ubsec_q { @@ -59,6 +61,15 @@ struct ubsec_q { int q_dst_packl[MAX_SCATTER]; int q_dst_npa, q_dst_l; u_int32_t q_macbuf[5]; + struct ubsec_session * q_ses; +}; + +struct ubsec_session { + u_int32_t ses_used; + u_int32_t ses_deskey[6]; /* 3DES key */ + u_int32_t ses_hminner[5]; /* hmac inner state */ + u_int32_t ses_hmouter[5]; /* hmac outer state */ + u_int32_t ses_iv[2]; /* [3]DES iv */ }; /* Maximum queue length */ |