1104476Ssam/* $OpenBSD: cryptosoft.c,v 1.35 2002/04/26 08:43:50 deraadt Exp $ */ 2104476Ssam 3139825Simp/*- 4104476Ssam * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) 5167755Ssam * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting 6104476Ssam * 7104476Ssam * This code was written by Angelos D. Keromytis in Athens, Greece, in 8104476Ssam * February 2000. Network Security Technologies Inc. (NSTI) kindly 9104476Ssam * supported the development of this code. 10104476Ssam * 11104476Ssam * Copyright (c) 2000, 2001 Angelos D. Keromytis 12104476Ssam * 13104476Ssam * Permission to use, copy, and modify this software with or without fee 14104476Ssam * is hereby granted, provided that this entire notice is included in 15104476Ssam * all source code copies of any software which is or includes a copy or 16104476Ssam * modification of this software. 17104476Ssam * 18104476Ssam * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 19104476Ssam * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 20104476Ssam * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 21104476Ssam * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 22104476Ssam * PURPOSE. 23104476Ssam */ 24104476Ssam 25116191Sobrien#include <sys/cdefs.h> 26116191Sobrien__FBSDID("$FreeBSD$"); 27116191Sobrien 28104476Ssam#include <sys/param.h> 29104476Ssam#include <sys/systm.h> 30104476Ssam#include <sys/malloc.h> 31104476Ssam#include <sys/mbuf.h> 32167755Ssam#include <sys/module.h> 33104476Ssam#include <sys/sysctl.h> 34104476Ssam#include <sys/errno.h> 35104476Ssam#include <sys/random.h> 36104476Ssam#include <sys/kernel.h> 37104476Ssam#include <sys/uio.h> 38104476Ssam 39104476Ssam#include <crypto/blowfish/blowfish.h> 40104476Ssam#include <crypto/sha1.h> 41104476Ssam#include <opencrypto/rmd160.h> 42143406Sume#include <opencrypto/cast.h> 43104476Ssam#include <opencrypto/skipjack.h> 44104476Ssam#include <sys/md5.h> 45104476Ssam 46104476Ssam#include <opencrypto/cryptodev.h> 47104476Ssam#include <opencrypto/cryptosoft.h> 48104476Ssam#include <opencrypto/xform.h> 49104476Ssam 50167755Ssam#include <sys/kobj.h> 51167755Ssam#include <sys/bus.h> 52167755Ssam#include "cryptodev_if.h" 53104476Ssam 54167755Ssamstatic int32_t swcr_id; 55167755Ssamstatic struct swcr_data **swcr_sessions = NULL; 56167755Ssamstatic u_int32_t swcr_sesnum; 57104476Ssam 58167755Ssamu_int8_t hmac_ipad_buffer[HMAC_MAX_BLOCK_LEN]; 59167755Ssamu_int8_t hmac_opad_buffer[HMAC_MAX_BLOCK_LEN]; 60167755Ssam 61104476Ssamstatic int swcr_encdec(struct cryptodesc *, struct swcr_data *, caddr_t, int); 62159242Spjdstatic int swcr_authcompute(struct cryptodesc *, struct swcr_data *, caddr_t, int); 63104476Ssamstatic int swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int); 64167755Ssamstatic int swcr_freesession(device_t dev, u_int64_t tid); 65104476Ssam 66104476Ssam/* 67104476Ssam * Apply a symmetric encryption/decryption algorithm. 68104476Ssam */ 69104476Ssamstatic int 70104476Ssamswcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf, 71159242Spjd int flags) 72104476Ssam{ 73104476Ssam unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN], *idat; 74104476Ssam unsigned char *ivp, piv[EALG_MAX_BLOCK_LEN]; 75104476Ssam struct enc_xform *exf; 76104476Ssam int i, k, j, blks; 77104476Ssam 78104476Ssam exf = sw->sw_exf; 79104476Ssam blks = exf->blocksize; 80104476Ssam 81104476Ssam /* Check for non-padded data */ 82104476Ssam if (crd->crd_len % blks) 83104476Ssam return EINVAL; 84104476Ssam 85104476Ssam /* Initialize the IV */ 86104476Ssam if (crd->crd_flags & CRD_F_ENCRYPT) { 87104476Ssam /* IV explicitly provided ? */ 88104476Ssam if (crd->crd_flags & CRD_F_IV_EXPLICIT) 89104476Ssam bcopy(crd->crd_iv, iv, blks); 90157637Spjd else 91157637Spjd arc4rand(iv, blks, 0); 92104476Ssam 93104476Ssam /* Do we need to write the IV */ 94159242Spjd if (!(crd->crd_flags & CRD_F_IV_PRESENT)) 95159242Spjd crypto_copyback(flags, buf, crd->crd_inject, blks, iv); 96104476Ssam 97104476Ssam } else { /* Decryption */ 98104476Ssam /* IV explicitly provided ? */ 99104476Ssam if (crd->crd_flags & CRD_F_IV_EXPLICIT) 100104476Ssam bcopy(crd->crd_iv, iv, blks); 101104476Ssam else { 102104476Ssam /* Get IV off buf */ 103159242Spjd crypto_copydata(flags, buf, crd->crd_inject, blks, iv); 104104476Ssam } 105104476Ssam } 106104476Ssam 107125330Sphk if (crd->crd_flags & CRD_F_KEY_EXPLICIT) { 108125330Sphk int error; 109125330Sphk 110125330Sphk if (sw->sw_kschedule) 111125330Sphk exf->zerokey(&(sw->sw_kschedule)); 112125330Sphk error = exf->setkey(&sw->sw_kschedule, 113125330Sphk crd->crd_key, crd->crd_klen / 8); 114125330Sphk if (error) 115125330Sphk return (error); 116125330Sphk } 117213068Spjd 118104476Ssam ivp = iv; 119104476Ssam 120213068Spjd /* 121213068Spjd * xforms that provide a reinit method perform all IV 122213068Spjd * handling themselves. 123213068Spjd */ 124213068Spjd if (exf->reinit) 125213068Spjd exf->reinit(sw->sw_kschedule, iv); 126213068Spjd 127159242Spjd if (flags & CRYPTO_F_IMBUF) { 128104476Ssam struct mbuf *m = (struct mbuf *) buf; 129104476Ssam 130104476Ssam /* Find beginning of data */ 131104476Ssam m = m_getptr(m, crd->crd_skip, &k); 132104476Ssam if (m == NULL) 133104476Ssam return EINVAL; 134104476Ssam 135104476Ssam i = crd->crd_len; 136104476Ssam 137104476Ssam while (i > 0) { 138104476Ssam /* 139104476Ssam * If there's insufficient data at the end of 140104476Ssam * an mbuf, we have to do some copying. 141104476Ssam */ 142104476Ssam if (m->m_len < k + blks && m->m_len != k) { 143104476Ssam m_copydata(m, k, blks, blk); 144104476Ssam 145104476Ssam /* Actual encryption/decryption */ 146213068Spjd if (exf->reinit) { 147213068Spjd if (crd->crd_flags & CRD_F_ENCRYPT) { 148213068Spjd exf->encrypt(sw->sw_kschedule, 149213068Spjd blk); 150213068Spjd } else { 151213068Spjd exf->decrypt(sw->sw_kschedule, 152213068Spjd blk); 153213068Spjd } 154213068Spjd } else if (crd->crd_flags & CRD_F_ENCRYPT) { 155104476Ssam /* XOR with previous block */ 156104476Ssam for (j = 0; j < blks; j++) 157104476Ssam blk[j] ^= ivp[j]; 158104476Ssam 159104476Ssam exf->encrypt(sw->sw_kschedule, blk); 160104476Ssam 161104476Ssam /* 162104476Ssam * Keep encrypted block for XOR'ing 163104476Ssam * with next block 164104476Ssam */ 165104476Ssam bcopy(blk, iv, blks); 166104476Ssam ivp = iv; 167104476Ssam } else { /* decrypt */ 168104476Ssam /* 169104476Ssam * Keep encrypted block for XOR'ing 170104476Ssam * with next block 171104476Ssam */ 172104476Ssam if (ivp == iv) 173104476Ssam bcopy(blk, piv, blks); 174104476Ssam else 175104476Ssam bcopy(blk, iv, blks); 176104476Ssam 177104476Ssam exf->decrypt(sw->sw_kschedule, blk); 178104476Ssam 179104476Ssam /* XOR with previous block */ 180104476Ssam for (j = 0; j < blks; j++) 181104476Ssam blk[j] ^= ivp[j]; 182104476Ssam 183104476Ssam if (ivp == iv) 184104476Ssam bcopy(piv, iv, blks); 185104476Ssam else 186104476Ssam ivp = iv; 187104476Ssam } 188104476Ssam 189104476Ssam /* Copy back decrypted block */ 190104476Ssam m_copyback(m, k, blks, blk); 191104476Ssam 192104476Ssam /* Advance pointer */ 193104476Ssam m = m_getptr(m, k + blks, &k); 194104476Ssam if (m == NULL) 195104476Ssam return EINVAL; 196104476Ssam 197104476Ssam i -= blks; 198104476Ssam 199104476Ssam /* Could be done... */ 200104476Ssam if (i == 0) 201104476Ssam break; 202104476Ssam } 203104476Ssam 204104476Ssam /* Skip possibly empty mbufs */ 205104476Ssam if (k == m->m_len) { 206104476Ssam for (m = m->m_next; m && m->m_len == 0; 207104476Ssam m = m->m_next) 208104476Ssam ; 209104476Ssam k = 0; 210104476Ssam } 211104476Ssam 212104476Ssam /* Sanity check */ 213104476Ssam if (m == NULL) 214104476Ssam return EINVAL; 215104476Ssam 216104476Ssam /* 217104476Ssam * Warning: idat may point to garbage here, but 218104476Ssam * we only use it in the while() loop, only if 219104476Ssam * there are indeed enough data. 220104476Ssam */ 221104476Ssam idat = mtod(m, unsigned char *) + k; 222104476Ssam 223104476Ssam while (m->m_len >= k + blks && i > 0) { 224213068Spjd if (exf->reinit) { 225213068Spjd if (crd->crd_flags & CRD_F_ENCRYPT) { 226213068Spjd exf->encrypt(sw->sw_kschedule, 227213068Spjd idat); 228213068Spjd } else { 229213068Spjd exf->decrypt(sw->sw_kschedule, 230213068Spjd idat); 231213068Spjd } 232213068Spjd } else if (crd->crd_flags & CRD_F_ENCRYPT) { 233104476Ssam /* XOR with previous block/IV */ 234104476Ssam for (j = 0; j < blks; j++) 235104476Ssam idat[j] ^= ivp[j]; 236104476Ssam 237104476Ssam exf->encrypt(sw->sw_kschedule, idat); 238104476Ssam ivp = idat; 239104476Ssam } else { /* decrypt */ 240104476Ssam /* 241104476Ssam * Keep encrypted block to be used 242104476Ssam * in next block's processing. 243104476Ssam */ 244104476Ssam if (ivp == iv) 245104476Ssam bcopy(idat, piv, blks); 246104476Ssam else 247104476Ssam bcopy(idat, iv, blks); 248104476Ssam 249104476Ssam exf->decrypt(sw->sw_kschedule, idat); 250104476Ssam 251104476Ssam /* XOR with previous block/IV */ 252104476Ssam for (j = 0; j < blks; j++) 253104476Ssam idat[j] ^= ivp[j]; 254104476Ssam 255104476Ssam if (ivp == iv) 256104476Ssam bcopy(piv, iv, blks); 257104476Ssam else 258104476Ssam ivp = iv; 259104476Ssam } 260104476Ssam 261104476Ssam idat += blks; 262104476Ssam k += blks; 263104476Ssam i -= blks; 264104476Ssam } 265104476Ssam } 266104476Ssam 267104476Ssam return 0; /* Done with mbuf encryption/decryption */ 268159242Spjd } else if (flags & CRYPTO_F_IOV) { 269104476Ssam struct uio *uio = (struct uio *) buf; 270104476Ssam struct iovec *iov; 271104476Ssam 272104476Ssam /* Find beginning of data */ 273104476Ssam iov = cuio_getptr(uio, crd->crd_skip, &k); 274104476Ssam if (iov == NULL) 275104476Ssam return EINVAL; 276104476Ssam 277104476Ssam i = crd->crd_len; 278104476Ssam 279104476Ssam while (i > 0) { 280104476Ssam /* 281104476Ssam * If there's insufficient data at the end of 282104476Ssam * an iovec, we have to do some copying. 283104476Ssam */ 284104476Ssam if (iov->iov_len < k + blks && iov->iov_len != k) { 285104476Ssam cuio_copydata(uio, k, blks, blk); 286104476Ssam 287104476Ssam /* Actual encryption/decryption */ 288213068Spjd if (exf->reinit) { 289213068Spjd if (crd->crd_flags & CRD_F_ENCRYPT) { 290213068Spjd exf->encrypt(sw->sw_kschedule, 291213068Spjd blk); 292213068Spjd } else { 293213068Spjd exf->decrypt(sw->sw_kschedule, 294213068Spjd blk); 295213068Spjd } 296213068Spjd } else if (crd->crd_flags & CRD_F_ENCRYPT) { 297104476Ssam /* XOR with previous block */ 298104476Ssam for (j = 0; j < blks; j++) 299104476Ssam blk[j] ^= ivp[j]; 300104476Ssam 301104476Ssam exf->encrypt(sw->sw_kschedule, blk); 302104476Ssam 303104476Ssam /* 304104476Ssam * Keep encrypted block for XOR'ing 305104476Ssam * with next block 306104476Ssam */ 307104476Ssam bcopy(blk, iv, blks); 308104476Ssam ivp = iv; 309104476Ssam } else { /* decrypt */ 310104476Ssam /* 311104476Ssam * Keep encrypted block for XOR'ing 312104476Ssam * with next block 313104476Ssam */ 314104476Ssam if (ivp == iv) 315104476Ssam bcopy(blk, piv, blks); 316104476Ssam else 317104476Ssam bcopy(blk, iv, blks); 318104476Ssam 319104476Ssam exf->decrypt(sw->sw_kschedule, blk); 320104476Ssam 321104476Ssam /* XOR with previous block */ 322104476Ssam for (j = 0; j < blks; j++) 323104476Ssam blk[j] ^= ivp[j]; 324104476Ssam 325104476Ssam if (ivp == iv) 326104476Ssam bcopy(piv, iv, blks); 327104476Ssam else 328104476Ssam ivp = iv; 329104476Ssam } 330104476Ssam 331104476Ssam /* Copy back decrypted block */ 332104476Ssam cuio_copyback(uio, k, blks, blk); 333104476Ssam 334104476Ssam /* Advance pointer */ 335104476Ssam iov = cuio_getptr(uio, k + blks, &k); 336104476Ssam if (iov == NULL) 337104476Ssam return EINVAL; 338104476Ssam 339104476Ssam i -= blks; 340104476Ssam 341104476Ssam /* Could be done... */ 342104476Ssam if (i == 0) 343104476Ssam break; 344104476Ssam } 345104476Ssam 346104476Ssam /* 347104476Ssam * Warning: idat may point to garbage here, but 348104476Ssam * we only use it in the while() loop, only if 349104476Ssam * there are indeed enough data. 350104476Ssam */ 351104908Smike idat = (char *)iov->iov_base + k; 352104476Ssam 353104476Ssam while (iov->iov_len >= k + blks && i > 0) { 354213068Spjd if (exf->reinit) { 355213068Spjd if (crd->crd_flags & CRD_F_ENCRYPT) { 356213068Spjd exf->encrypt(sw->sw_kschedule, 357213068Spjd idat); 358213068Spjd } else { 359213068Spjd exf->decrypt(sw->sw_kschedule, 360213068Spjd idat); 361213068Spjd } 362213068Spjd } else if (crd->crd_flags & CRD_F_ENCRYPT) { 363104476Ssam /* XOR with previous block/IV */ 364104476Ssam for (j = 0; j < blks; j++) 365104476Ssam idat[j] ^= ivp[j]; 366104476Ssam 367104476Ssam exf->encrypt(sw->sw_kschedule, idat); 368104476Ssam ivp = idat; 369104476Ssam } else { /* decrypt */ 370104476Ssam /* 371104476Ssam * Keep encrypted block to be used 372104476Ssam * in next block's processing. 373104476Ssam */ 374104476Ssam if (ivp == iv) 375104476Ssam bcopy(idat, piv, blks); 376104476Ssam else 377104476Ssam bcopy(idat, iv, blks); 378104476Ssam 379104476Ssam exf->decrypt(sw->sw_kschedule, idat); 380104476Ssam 381104476Ssam /* XOR with previous block/IV */ 382104476Ssam for (j = 0; j < blks; j++) 383104476Ssam idat[j] ^= ivp[j]; 384104476Ssam 385104476Ssam if (ivp == iv) 386104476Ssam bcopy(piv, iv, blks); 387104476Ssam else 388104476Ssam ivp = iv; 389104476Ssam } 390104476Ssam 391104476Ssam idat += blks; 392104476Ssam k += blks; 393104476Ssam i -= blks; 394104476Ssam } 395184477Sdfr if (k == iov->iov_len) { 396184477Sdfr iov++; 397184477Sdfr k = 0; 398184477Sdfr } 399104476Ssam } 400104476Ssam 401158703Spjd return 0; /* Done with iovec encryption/decryption */ 402159242Spjd } else { /* contiguous buffer */ 403213068Spjd if (exf->reinit) { 404159242Spjd for (i = crd->crd_skip; 405159242Spjd i < crd->crd_skip + crd->crd_len; i += blks) { 406213068Spjd if (crd->crd_flags & CRD_F_ENCRYPT) 407213068Spjd exf->encrypt(sw->sw_kschedule, buf + i); 408213068Spjd else 409213068Spjd exf->decrypt(sw->sw_kschedule, buf + i); 410213068Spjd } 411213068Spjd } else if (crd->crd_flags & CRD_F_ENCRYPT) { 412213068Spjd for (i = crd->crd_skip; 413213068Spjd i < crd->crd_skip + crd->crd_len; i += blks) { 414159242Spjd /* XOR with the IV/previous block, as appropriate. */ 415159242Spjd if (i == crd->crd_skip) 416159242Spjd for (k = 0; k < blks; k++) 417159242Spjd buf[i + k] ^= ivp[k]; 418159242Spjd else 419159242Spjd for (k = 0; k < blks; k++) 420159242Spjd buf[i + k] ^= buf[i + k - blks]; 421159242Spjd exf->encrypt(sw->sw_kschedule, buf + i); 422159242Spjd } 423159242Spjd } else { /* Decrypt */ 424159242Spjd /* 425159242Spjd * Start at the end, so we don't need to keep the encrypted 426159242Spjd * block as the IV for the next block. 427159242Spjd */ 428159242Spjd for (i = crd->crd_skip + crd->crd_len - blks; 429159242Spjd i >= crd->crd_skip; i -= blks) { 430159242Spjd exf->decrypt(sw->sw_kschedule, buf + i); 431159242Spjd 432159242Spjd /* XOR with the IV/previous block, as appropriate */ 433159242Spjd if (i == crd->crd_skip) 434159242Spjd for (k = 0; k < blks; k++) 435159242Spjd buf[i + k] ^= ivp[k]; 436159242Spjd else 437159242Spjd for (k = 0; k < blks; k++) 438159242Spjd buf[i + k] ^= buf[i + k - blks]; 439159242Spjd } 440159242Spjd } 441159242Spjd 442159242Spjd return 0; /* Done with contiguous buffer encryption/decryption */ 443104476Ssam } 444104476Ssam 445104476Ssam /* Unreachable */ 446104476Ssam return EINVAL; 447104476Ssam} 448104476Ssam 449158703Spjdstatic void 450158703Spjdswcr_authprepare(struct auth_hash *axf, struct swcr_data *sw, u_char *key, 451158703Spjd int klen) 452158703Spjd{ 453158703Spjd int k; 454158703Spjd 455158703Spjd klen /= 8; 456158703Spjd 457158703Spjd switch (axf->type) { 458158703Spjd case CRYPTO_MD5_HMAC: 459158703Spjd case CRYPTO_SHA1_HMAC: 460158703Spjd case CRYPTO_SHA2_256_HMAC: 461158703Spjd case CRYPTO_SHA2_384_HMAC: 462158703Spjd case CRYPTO_SHA2_512_HMAC: 463158703Spjd case CRYPTO_NULL_HMAC: 464158703Spjd case CRYPTO_RIPEMD160_HMAC: 465158703Spjd for (k = 0; k < klen; k++) 466158703Spjd key[k] ^= HMAC_IPAD_VAL; 467158703Spjd 468158703Spjd axf->Init(sw->sw_ictx); 469158703Spjd axf->Update(sw->sw_ictx, key, klen); 470158703Spjd axf->Update(sw->sw_ictx, hmac_ipad_buffer, axf->blocksize - klen); 471158703Spjd 472158703Spjd for (k = 0; k < klen; k++) 473158703Spjd key[k] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); 474158703Spjd 475158703Spjd axf->Init(sw->sw_octx); 476158703Spjd axf->Update(sw->sw_octx, key, klen); 477158703Spjd axf->Update(sw->sw_octx, hmac_opad_buffer, axf->blocksize - klen); 478158703Spjd 479158703Spjd for (k = 0; k < klen; k++) 480158703Spjd key[k] ^= HMAC_OPAD_VAL; 481158703Spjd break; 482158703Spjd case CRYPTO_MD5_KPDK: 483158703Spjd case CRYPTO_SHA1_KPDK: 484187826Sbz { 485201898Sbz /* 486201898Sbz * We need a buffer that can hold an md5 and a sha1 result 487201898Sbz * just to throw it away. 488201898Sbz * What we do here is the initial part of: 489201898Sbz * ALGO( key, keyfill, .. ) 490201898Sbz * adding the key to sw_ictx and abusing Final() to get the 491201898Sbz * "keyfill" padding. 492201898Sbz * In addition we abuse the sw_octx to save the key to have 493201898Sbz * it to be able to append it at the end in swcr_authcompute(). 494201898Sbz */ 495187826Sbz u_char buf[SHA1_RESULTLEN]; 496187826Sbz 497158703Spjd sw->sw_klen = klen; 498158703Spjd bcopy(key, sw->sw_octx, klen); 499158703Spjd axf->Init(sw->sw_ictx); 500158703Spjd axf->Update(sw->sw_ictx, key, klen); 501187826Sbz axf->Final(buf, sw->sw_ictx); 502158703Spjd break; 503187826Sbz } 504158703Spjd default: 505158703Spjd printf("%s: CRD_F_KEY_EXPLICIT flag given, but algorithm %d " 506158703Spjd "doesn't use keys.\n", __func__, axf->type); 507158703Spjd } 508158703Spjd} 509158703Spjd 510104476Ssam/* 511104476Ssam * Compute keyed-hash authenticator. 512104476Ssam */ 513104476Ssamstatic int 514159223Spjdswcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf, 515159242Spjd int flags) 516104476Ssam{ 517159228Spjd unsigned char aalg[HASH_MAX_LEN]; 518104476Ssam struct auth_hash *axf; 519104476Ssam union authctx ctx; 520104476Ssam int err; 521104476Ssam 522104476Ssam if (sw->sw_ictx == 0) 523104476Ssam return EINVAL; 524104476Ssam 525104476Ssam axf = sw->sw_axf; 526104476Ssam 527158703Spjd if (crd->crd_flags & CRD_F_KEY_EXPLICIT) 528158703Spjd swcr_authprepare(axf, sw, crd->crd_key, crd->crd_klen); 529158703Spjd 530104476Ssam bcopy(sw->sw_ictx, &ctx, axf->ctxsize); 531104476Ssam 532159242Spjd err = crypto_apply(flags, buf, crd->crd_skip, crd->crd_len, 533159242Spjd (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx); 534159242Spjd if (err) 535159242Spjd return err; 536104476Ssam 537104476Ssam switch (sw->sw_alg) { 538104476Ssam case CRYPTO_MD5_HMAC: 539104476Ssam case CRYPTO_SHA1_HMAC: 540158703Spjd case CRYPTO_SHA2_256_HMAC: 541158703Spjd case CRYPTO_SHA2_384_HMAC: 542158703Spjd case CRYPTO_SHA2_512_HMAC: 543104476Ssam case CRYPTO_RIPEMD160_HMAC: 544104476Ssam if (sw->sw_octx == NULL) 545104476Ssam return EINVAL; 546104476Ssam 547104476Ssam axf->Final(aalg, &ctx); 548104476Ssam bcopy(sw->sw_octx, &ctx, axf->ctxsize); 549104476Ssam axf->Update(&ctx, aalg, axf->hashsize); 550104476Ssam axf->Final(aalg, &ctx); 551104476Ssam break; 552104476Ssam 553104476Ssam case CRYPTO_MD5_KPDK: 554104476Ssam case CRYPTO_SHA1_KPDK: 555201898Sbz /* If we have no key saved, return error. */ 556104476Ssam if (sw->sw_octx == NULL) 557104476Ssam return EINVAL; 558104476Ssam 559201898Sbz /* 560201898Sbz * Add the trailing copy of the key (see comment in 561201898Sbz * swcr_authprepare()) after the data: 562201898Sbz * ALGO( .., key, algofill ) 563201898Sbz * and let Final() do the proper, natural "algofill" 564201898Sbz * padding. 565201898Sbz */ 566104476Ssam axf->Update(&ctx, sw->sw_octx, sw->sw_klen); 567104476Ssam axf->Final(aalg, &ctx); 568104476Ssam break; 569104476Ssam 570104476Ssam case CRYPTO_NULL_HMAC: 571104476Ssam axf->Final(aalg, &ctx); 572104476Ssam break; 573104476Ssam } 574104476Ssam 575104476Ssam /* Inject the authentication data */ 576159242Spjd crypto_copyback(flags, buf, crd->crd_inject, 577158703Spjd sw->sw_mlen == 0 ? axf->hashsize : sw->sw_mlen, aalg); 578104476Ssam return 0; 579104476Ssam} 580104476Ssam 581104476Ssam/* 582104476Ssam * Apply a compression/decompression algorithm 583104476Ssam */ 584104476Ssamstatic int 585104476Ssamswcr_compdec(struct cryptodesc *crd, struct swcr_data *sw, 586159242Spjd caddr_t buf, int flags) 587104476Ssam{ 588104476Ssam u_int8_t *data, *out; 589104476Ssam struct comp_algo *cxf; 590104476Ssam int adj; 591104476Ssam u_int32_t result; 592104476Ssam 593104476Ssam cxf = sw->sw_cxf; 594104476Ssam 595104476Ssam /* We must handle the whole buffer of data in one time 596104476Ssam * then if there is not all the data in the mbuf, we must 597104476Ssam * copy in a buffer. 598104476Ssam */ 599104476Ssam 600184205Sdes data = malloc(crd->crd_len, M_CRYPTO_DATA, M_NOWAIT); 601104476Ssam if (data == NULL) 602104476Ssam return (EINVAL); 603159242Spjd crypto_copydata(flags, buf, crd->crd_skip, crd->crd_len, data); 604104476Ssam 605104476Ssam if (crd->crd_flags & CRD_F_COMP) 606104476Ssam result = cxf->compress(data, crd->crd_len, &out); 607104476Ssam else 608104476Ssam result = cxf->decompress(data, crd->crd_len, &out); 609104476Ssam 610184205Sdes free(data, M_CRYPTO_DATA); 611104476Ssam if (result == 0) 612104476Ssam return EINVAL; 613104476Ssam 614104476Ssam /* Copy back the (de)compressed data. m_copyback is 615104476Ssam * extending the mbuf as necessary. 616104476Ssam */ 617104476Ssam sw->sw_size = result; 618104476Ssam /* Check the compressed size when doing compression */ 619104476Ssam if (crd->crd_flags & CRD_F_COMP) { 620199906Sbz if (result >= crd->crd_len) { 621104476Ssam /* Compression was useless, we lost time */ 622184205Sdes free(out, M_CRYPTO_DATA); 623104476Ssam return 0; 624104476Ssam } 625104476Ssam } 626104476Ssam 627159242Spjd crypto_copyback(flags, buf, crd->crd_skip, result, out); 628104476Ssam if (result < crd->crd_len) { 629104476Ssam adj = result - crd->crd_len; 630159242Spjd if (flags & CRYPTO_F_IMBUF) { 631104476Ssam adj = result - crd->crd_len; 632104476Ssam m_adj((struct mbuf *)buf, adj); 633159242Spjd } else if (flags & CRYPTO_F_IOV) { 634104476Ssam struct uio *uio = (struct uio *)buf; 635104476Ssam int ind; 636104476Ssam 637104476Ssam adj = crd->crd_len - result; 638104476Ssam ind = uio->uio_iovcnt - 1; 639104476Ssam 640104476Ssam while (adj > 0 && ind >= 0) { 641104476Ssam if (adj < uio->uio_iov[ind].iov_len) { 642104476Ssam uio->uio_iov[ind].iov_len -= adj; 643104476Ssam break; 644104476Ssam } 645104476Ssam 646104476Ssam adj -= uio->uio_iov[ind].iov_len; 647104476Ssam uio->uio_iov[ind].iov_len = 0; 648104476Ssam ind--; 649104476Ssam uio->uio_iovcnt--; 650104476Ssam } 651104476Ssam } 652104476Ssam } 653184205Sdes free(out, M_CRYPTO_DATA); 654104476Ssam return 0; 655104476Ssam} 656104476Ssam 657104476Ssam/* 658104476Ssam * Generate a new software session. 659104476Ssam */ 660104476Ssamstatic int 661167755Ssamswcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri) 662104476Ssam{ 663104476Ssam struct swcr_data **swd; 664104476Ssam struct auth_hash *axf; 665104476Ssam struct enc_xform *txf; 666104476Ssam struct comp_algo *cxf; 667104476Ssam u_int32_t i; 668158703Spjd int error; 669104476Ssam 670104476Ssam if (sid == NULL || cri == NULL) 671104476Ssam return EINVAL; 672104476Ssam 673104476Ssam if (swcr_sessions) { 674104476Ssam for (i = 1; i < swcr_sesnum; i++) 675104476Ssam if (swcr_sessions[i] == NULL) 676104476Ssam break; 677104476Ssam } else 678104476Ssam i = 1; /* NB: to silence compiler warning */ 679104476Ssam 680104476Ssam if (swcr_sessions == NULL || i == swcr_sesnum) { 681104476Ssam if (swcr_sessions == NULL) { 682104476Ssam i = 1; /* We leave swcr_sessions[0] empty */ 683104476Ssam swcr_sesnum = CRYPTO_SW_SESSIONS; 684104476Ssam } else 685104476Ssam swcr_sesnum *= 2; 686104476Ssam 687104476Ssam swd = malloc(swcr_sesnum * sizeof(struct swcr_data *), 688104476Ssam M_CRYPTO_DATA, M_NOWAIT|M_ZERO); 689104476Ssam if (swd == NULL) { 690104476Ssam /* Reset session number */ 691104476Ssam if (swcr_sesnum == CRYPTO_SW_SESSIONS) 692104476Ssam swcr_sesnum = 0; 693104476Ssam else 694104476Ssam swcr_sesnum /= 2; 695104476Ssam return ENOBUFS; 696104476Ssam } 697104476Ssam 698104476Ssam /* Copy existing sessions */ 699167755Ssam if (swcr_sessions != NULL) { 700104476Ssam bcopy(swcr_sessions, swd, 701104476Ssam (swcr_sesnum / 2) * sizeof(struct swcr_data *)); 702104476Ssam free(swcr_sessions, M_CRYPTO_DATA); 703104476Ssam } 704104476Ssam 705104476Ssam swcr_sessions = swd; 706104476Ssam } 707104476Ssam 708104476Ssam swd = &swcr_sessions[i]; 709104476Ssam *sid = i; 710104476Ssam 711104476Ssam while (cri) { 712184205Sdes *swd = malloc(sizeof(struct swcr_data), 713104476Ssam M_CRYPTO_DATA, M_NOWAIT|M_ZERO); 714104476Ssam if (*swd == NULL) { 715167755Ssam swcr_freesession(dev, i); 716104476Ssam return ENOBUFS; 717104476Ssam } 718104476Ssam 719104476Ssam switch (cri->cri_alg) { 720104476Ssam case CRYPTO_DES_CBC: 721104476Ssam txf = &enc_xform_des; 722104476Ssam goto enccommon; 723104476Ssam case CRYPTO_3DES_CBC: 724104476Ssam txf = &enc_xform_3des; 725104476Ssam goto enccommon; 726104476Ssam case CRYPTO_BLF_CBC: 727104476Ssam txf = &enc_xform_blf; 728104476Ssam goto enccommon; 729104476Ssam case CRYPTO_CAST_CBC: 730104476Ssam txf = &enc_xform_cast5; 731104476Ssam goto enccommon; 732104476Ssam case CRYPTO_SKIPJACK_CBC: 733104476Ssam txf = &enc_xform_skipjack; 734104476Ssam goto enccommon; 735104476Ssam case CRYPTO_RIJNDAEL128_CBC: 736104476Ssam txf = &enc_xform_rijndael128; 737104476Ssam goto enccommon; 738213068Spjd case CRYPTO_AES_XTS: 739213068Spjd txf = &enc_xform_aes_xts; 740213068Spjd goto enccommon; 741169425Sgnn case CRYPTO_CAMELLIA_CBC: 742169425Sgnn txf = &enc_xform_camellia; 743169425Sgnn goto enccommon; 744104476Ssam case CRYPTO_NULL_CBC: 745104476Ssam txf = &enc_xform_null; 746104476Ssam goto enccommon; 747104476Ssam enccommon: 748158703Spjd if (cri->cri_key != NULL) { 749158703Spjd error = txf->setkey(&((*swd)->sw_kschedule), 750158703Spjd cri->cri_key, cri->cri_klen / 8); 751158703Spjd if (error) { 752167755Ssam swcr_freesession(dev, i); 753158703Spjd return error; 754158703Spjd } 755104476Ssam } 756104476Ssam (*swd)->sw_exf = txf; 757104476Ssam break; 758104476Ssam 759104476Ssam case CRYPTO_MD5_HMAC: 760158703Spjd axf = &auth_hash_hmac_md5; 761104476Ssam goto authcommon; 762104476Ssam case CRYPTO_SHA1_HMAC: 763158703Spjd axf = &auth_hash_hmac_sha1; 764104476Ssam goto authcommon; 765158703Spjd case CRYPTO_SHA2_256_HMAC: 766158703Spjd axf = &auth_hash_hmac_sha2_256; 767104476Ssam goto authcommon; 768158703Spjd case CRYPTO_SHA2_384_HMAC: 769158703Spjd axf = &auth_hash_hmac_sha2_384; 770158703Spjd goto authcommon; 771158703Spjd case CRYPTO_SHA2_512_HMAC: 772158703Spjd axf = &auth_hash_hmac_sha2_512; 773158703Spjd goto authcommon; 774104476Ssam case CRYPTO_NULL_HMAC: 775104476Ssam axf = &auth_hash_null; 776104476Ssam goto authcommon; 777104476Ssam case CRYPTO_RIPEMD160_HMAC: 778158703Spjd axf = &auth_hash_hmac_ripemd_160; 779104476Ssam authcommon: 780104476Ssam (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 781104476Ssam M_NOWAIT); 782104476Ssam if ((*swd)->sw_ictx == NULL) { 783167755Ssam swcr_freesession(dev, i); 784104476Ssam return ENOBUFS; 785104476Ssam } 786104476Ssam 787104476Ssam (*swd)->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA, 788104476Ssam M_NOWAIT); 789104476Ssam if ((*swd)->sw_octx == NULL) { 790167755Ssam swcr_freesession(dev, i); 791104476Ssam return ENOBUFS; 792104476Ssam } 793158703Spjd 794158703Spjd if (cri->cri_key != NULL) { 795158703Spjd swcr_authprepare(axf, *swd, cri->cri_key, 796158703Spjd cri->cri_klen); 797158703Spjd } 798158703Spjd 799158703Spjd (*swd)->sw_mlen = cri->cri_mlen; 800104476Ssam (*swd)->sw_axf = axf; 801104476Ssam break; 802104476Ssam 803104476Ssam case CRYPTO_MD5_KPDK: 804104476Ssam axf = &auth_hash_key_md5; 805104476Ssam goto auth2common; 806104476Ssam 807104476Ssam case CRYPTO_SHA1_KPDK: 808104476Ssam axf = &auth_hash_key_sha1; 809104476Ssam auth2common: 810104476Ssam (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 811104476Ssam M_NOWAIT); 812104476Ssam if ((*swd)->sw_ictx == NULL) { 813167755Ssam swcr_freesession(dev, i); 814104476Ssam return ENOBUFS; 815104476Ssam } 816104476Ssam 817158703Spjd (*swd)->sw_octx = malloc(cri->cri_klen / 8, 818158703Spjd M_CRYPTO_DATA, M_NOWAIT); 819104476Ssam if ((*swd)->sw_octx == NULL) { 820167755Ssam swcr_freesession(dev, i); 821104476Ssam return ENOBUFS; 822104476Ssam } 823158703Spjd 824158703Spjd /* Store the key so we can "append" it to the payload */ 825158703Spjd if (cri->cri_key != NULL) { 826158703Spjd swcr_authprepare(axf, *swd, cri->cri_key, 827158703Spjd cri->cri_klen); 828158703Spjd } 829158703Spjd 830158703Spjd (*swd)->sw_mlen = cri->cri_mlen; 831104476Ssam (*swd)->sw_axf = axf; 832104476Ssam break; 833104476Ssam#ifdef notdef 834104476Ssam case CRYPTO_MD5: 835104476Ssam axf = &auth_hash_md5; 836104476Ssam goto auth3common; 837104476Ssam 838104476Ssam case CRYPTO_SHA1: 839104476Ssam axf = &auth_hash_sha1; 840104476Ssam auth3common: 841104476Ssam (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 842104476Ssam M_NOWAIT); 843104476Ssam if ((*swd)->sw_ictx == NULL) { 844167755Ssam swcr_freesession(dev, i); 845104476Ssam return ENOBUFS; 846104476Ssam } 847104476Ssam 848104476Ssam axf->Init((*swd)->sw_ictx); 849158703Spjd (*swd)->sw_mlen = cri->cri_mlen; 850104476Ssam (*swd)->sw_axf = axf; 851104476Ssam break; 852104476Ssam#endif 853104476Ssam case CRYPTO_DEFLATE_COMP: 854104476Ssam cxf = &comp_algo_deflate; 855104476Ssam (*swd)->sw_cxf = cxf; 856104476Ssam break; 857104476Ssam default: 858167755Ssam swcr_freesession(dev, i); 859104476Ssam return EINVAL; 860104476Ssam } 861104476Ssam 862104476Ssam (*swd)->sw_alg = cri->cri_alg; 863104476Ssam cri = cri->cri_next; 864104476Ssam swd = &((*swd)->sw_next); 865104476Ssam } 866104476Ssam return 0; 867104476Ssam} 868104476Ssam 869104476Ssam/* 870104476Ssam * Free a session. 871104476Ssam */ 872104476Ssamstatic int 873167755Ssamswcr_freesession(device_t dev, u_int64_t tid) 874104476Ssam{ 875104476Ssam struct swcr_data *swd; 876104476Ssam struct enc_xform *txf; 877104476Ssam struct auth_hash *axf; 878104476Ssam struct comp_algo *cxf; 879116924Ssam u_int32_t sid = CRYPTO_SESID2LID(tid); 880104476Ssam 881104476Ssam if (sid > swcr_sesnum || swcr_sessions == NULL || 882104476Ssam swcr_sessions[sid] == NULL) 883104476Ssam return EINVAL; 884104476Ssam 885104476Ssam /* Silently accept and return */ 886104476Ssam if (sid == 0) 887104476Ssam return 0; 888104476Ssam 889104476Ssam while ((swd = swcr_sessions[sid]) != NULL) { 890104476Ssam swcr_sessions[sid] = swd->sw_next; 891104476Ssam 892104476Ssam switch (swd->sw_alg) { 893104476Ssam case CRYPTO_DES_CBC: 894104476Ssam case CRYPTO_3DES_CBC: 895104476Ssam case CRYPTO_BLF_CBC: 896104476Ssam case CRYPTO_CAST_CBC: 897104476Ssam case CRYPTO_SKIPJACK_CBC: 898104476Ssam case CRYPTO_RIJNDAEL128_CBC: 899213068Spjd case CRYPTO_AES_XTS: 900169425Sgnn case CRYPTO_CAMELLIA_CBC: 901104476Ssam case CRYPTO_NULL_CBC: 902104476Ssam txf = swd->sw_exf; 903104476Ssam 904104476Ssam if (swd->sw_kschedule) 905104476Ssam txf->zerokey(&(swd->sw_kschedule)); 906104476Ssam break; 907104476Ssam 908104476Ssam case CRYPTO_MD5_HMAC: 909104476Ssam case CRYPTO_SHA1_HMAC: 910158703Spjd case CRYPTO_SHA2_256_HMAC: 911158703Spjd case CRYPTO_SHA2_384_HMAC: 912158703Spjd case CRYPTO_SHA2_512_HMAC: 913104476Ssam case CRYPTO_RIPEMD160_HMAC: 914104476Ssam case CRYPTO_NULL_HMAC: 915104476Ssam axf = swd->sw_axf; 916104476Ssam 917104476Ssam if (swd->sw_ictx) { 918104476Ssam bzero(swd->sw_ictx, axf->ctxsize); 919104476Ssam free(swd->sw_ictx, M_CRYPTO_DATA); 920104476Ssam } 921104476Ssam if (swd->sw_octx) { 922104476Ssam bzero(swd->sw_octx, axf->ctxsize); 923104476Ssam free(swd->sw_octx, M_CRYPTO_DATA); 924104476Ssam } 925104476Ssam break; 926104476Ssam 927104476Ssam case CRYPTO_MD5_KPDK: 928104476Ssam case CRYPTO_SHA1_KPDK: 929104476Ssam axf = swd->sw_axf; 930104476Ssam 931104476Ssam if (swd->sw_ictx) { 932104476Ssam bzero(swd->sw_ictx, axf->ctxsize); 933104476Ssam free(swd->sw_ictx, M_CRYPTO_DATA); 934104476Ssam } 935104476Ssam if (swd->sw_octx) { 936104476Ssam bzero(swd->sw_octx, swd->sw_klen); 937104476Ssam free(swd->sw_octx, M_CRYPTO_DATA); 938104476Ssam } 939104476Ssam break; 940104476Ssam 941104476Ssam case CRYPTO_MD5: 942104476Ssam case CRYPTO_SHA1: 943104476Ssam axf = swd->sw_axf; 944104476Ssam 945104476Ssam if (swd->sw_ictx) 946104476Ssam free(swd->sw_ictx, M_CRYPTO_DATA); 947104476Ssam break; 948104476Ssam 949104476Ssam case CRYPTO_DEFLATE_COMP: 950104476Ssam cxf = swd->sw_cxf; 951104476Ssam break; 952104476Ssam } 953104476Ssam 954184205Sdes free(swd, M_CRYPTO_DATA); 955104476Ssam } 956104476Ssam return 0; 957104476Ssam} 958104476Ssam 959104476Ssam/* 960104476Ssam * Process a software request. 961104476Ssam */ 962104476Ssamstatic int 963167755Ssamswcr_process(device_t dev, struct cryptop *crp, int hint) 964104476Ssam{ 965104476Ssam struct cryptodesc *crd; 966104476Ssam struct swcr_data *sw; 967104476Ssam u_int32_t lid; 968104476Ssam 969104476Ssam /* Sanity check */ 970104476Ssam if (crp == NULL) 971104476Ssam return EINVAL; 972104476Ssam 973104476Ssam if (crp->crp_desc == NULL || crp->crp_buf == NULL) { 974104476Ssam crp->crp_etype = EINVAL; 975104476Ssam goto done; 976104476Ssam } 977104476Ssam 978104476Ssam lid = crp->crp_sid & 0xffffffff; 979104476Ssam if (lid >= swcr_sesnum || lid == 0 || swcr_sessions[lid] == NULL) { 980104476Ssam crp->crp_etype = ENOENT; 981104476Ssam goto done; 982104476Ssam } 983104476Ssam 984104476Ssam /* Go through crypto descriptors, processing as we go */ 985104476Ssam for (crd = crp->crp_desc; crd; crd = crd->crd_next) { 986104476Ssam /* 987104476Ssam * Find the crypto context. 988104476Ssam * 989104476Ssam * XXX Note that the logic here prevents us from having 990104476Ssam * XXX the same algorithm multiple times in a session 991104476Ssam * XXX (or rather, we can but it won't give us the right 992104476Ssam * XXX results). To do that, we'd need some way of differentiating 993104476Ssam * XXX between the various instances of an algorithm (so we can 994104476Ssam * XXX locate the correct crypto context). 995104476Ssam */ 996104476Ssam for (sw = swcr_sessions[lid]; 997104476Ssam sw && sw->sw_alg != crd->crd_alg; 998104476Ssam sw = sw->sw_next) 999104476Ssam ; 1000104476Ssam 1001104476Ssam /* No such context ? */ 1002104476Ssam if (sw == NULL) { 1003104476Ssam crp->crp_etype = EINVAL; 1004104476Ssam goto done; 1005104476Ssam } 1006104476Ssam switch (sw->sw_alg) { 1007104476Ssam case CRYPTO_DES_CBC: 1008104476Ssam case CRYPTO_3DES_CBC: 1009104476Ssam case CRYPTO_BLF_CBC: 1010104476Ssam case CRYPTO_CAST_CBC: 1011104476Ssam case CRYPTO_SKIPJACK_CBC: 1012104476Ssam case CRYPTO_RIJNDAEL128_CBC: 1013213068Spjd case CRYPTO_AES_XTS: 1014169425Sgnn case CRYPTO_CAMELLIA_CBC: 1015104476Ssam if ((crp->crp_etype = swcr_encdec(crd, sw, 1016159242Spjd crp->crp_buf, crp->crp_flags)) != 0) 1017104476Ssam goto done; 1018104476Ssam break; 1019104476Ssam case CRYPTO_NULL_CBC: 1020104476Ssam crp->crp_etype = 0; 1021104476Ssam break; 1022104476Ssam case CRYPTO_MD5_HMAC: 1023104476Ssam case CRYPTO_SHA1_HMAC: 1024158703Spjd case CRYPTO_SHA2_256_HMAC: 1025158703Spjd case CRYPTO_SHA2_384_HMAC: 1026158703Spjd case CRYPTO_SHA2_512_HMAC: 1027104476Ssam case CRYPTO_RIPEMD160_HMAC: 1028104476Ssam case CRYPTO_NULL_HMAC: 1029104476Ssam case CRYPTO_MD5_KPDK: 1030104476Ssam case CRYPTO_SHA1_KPDK: 1031104476Ssam case CRYPTO_MD5: 1032104476Ssam case CRYPTO_SHA1: 1033159223Spjd if ((crp->crp_etype = swcr_authcompute(crd, sw, 1034159242Spjd crp->crp_buf, crp->crp_flags)) != 0) 1035104476Ssam goto done; 1036104476Ssam break; 1037104476Ssam 1038104476Ssam case CRYPTO_DEFLATE_COMP: 1039104476Ssam if ((crp->crp_etype = swcr_compdec(crd, sw, 1040159242Spjd crp->crp_buf, crp->crp_flags)) != 0) 1041104476Ssam goto done; 1042104476Ssam else 1043104476Ssam crp->crp_olen = (int)sw->sw_size; 1044104476Ssam break; 1045104476Ssam 1046104476Ssam default: 1047104476Ssam /* Unknown/unsupported algorithm */ 1048104476Ssam crp->crp_etype = EINVAL; 1049104476Ssam goto done; 1050104476Ssam } 1051104476Ssam } 1052104476Ssam 1053104476Ssamdone: 1054104476Ssam crypto_done(crp); 1055104476Ssam return 0; 1056104476Ssam} 1057104476Ssam 1058104476Ssamstatic void 1059188154Simpswcr_identify(driver_t *drv, device_t parent) 1060104476Ssam{ 1061167755Ssam /* NB: order 10 is so we get attached after h/w devices */ 1062167755Ssam if (device_find_child(parent, "cryptosoft", -1) == NULL && 1063215295Smarius BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0) 1064167755Ssam panic("cryptosoft: could not attach"); 1065167755Ssam} 1066158703Spjd 1067167755Ssamstatic int 1068167755Ssamswcr_probe(device_t dev) 1069167755Ssam{ 1070167755Ssam device_set_desc(dev, "software crypto"); 1071215295Smarius return (BUS_PROBE_NOWILDCARD); 1072167755Ssam} 1073158703Spjd 1074167755Ssamstatic int 1075167755Ssamswcr_attach(device_t dev) 1076167755Ssam{ 1077167755Ssam memset(hmac_ipad_buffer, HMAC_IPAD_VAL, HMAC_MAX_BLOCK_LEN); 1078167755Ssam memset(hmac_opad_buffer, HMAC_OPAD_VAL, HMAC_MAX_BLOCK_LEN); 1079167755Ssam 1080167755Ssam swcr_id = crypto_get_driverid(dev, 1081167755Ssam CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC); 1082167755Ssam if (swcr_id < 0) { 1083167755Ssam device_printf(dev, "cannot initialize!"); 1084167755Ssam return ENOMEM; 1085167755Ssam } 1086104476Ssam#define REGISTER(alg) \ 1087167755Ssam crypto_register(swcr_id, alg, 0,0) 1088167755Ssam REGISTER(CRYPTO_DES_CBC); 1089104476Ssam REGISTER(CRYPTO_3DES_CBC); 1090104476Ssam REGISTER(CRYPTO_BLF_CBC); 1091104476Ssam REGISTER(CRYPTO_CAST_CBC); 1092104476Ssam REGISTER(CRYPTO_SKIPJACK_CBC); 1093104476Ssam REGISTER(CRYPTO_NULL_CBC); 1094104476Ssam REGISTER(CRYPTO_MD5_HMAC); 1095104476Ssam REGISTER(CRYPTO_SHA1_HMAC); 1096158703Spjd REGISTER(CRYPTO_SHA2_256_HMAC); 1097158703Spjd REGISTER(CRYPTO_SHA2_384_HMAC); 1098158703Spjd REGISTER(CRYPTO_SHA2_512_HMAC); 1099104476Ssam REGISTER(CRYPTO_RIPEMD160_HMAC); 1100104476Ssam REGISTER(CRYPTO_NULL_HMAC); 1101104476Ssam REGISTER(CRYPTO_MD5_KPDK); 1102104476Ssam REGISTER(CRYPTO_SHA1_KPDK); 1103104476Ssam REGISTER(CRYPTO_MD5); 1104104476Ssam REGISTER(CRYPTO_SHA1); 1105104476Ssam REGISTER(CRYPTO_RIJNDAEL128_CBC); 1106213068Spjd REGISTER(CRYPTO_AES_XTS); 1107169425Sgnn REGISTER(CRYPTO_CAMELLIA_CBC); 1108104476Ssam REGISTER(CRYPTO_DEFLATE_COMP); 1109104476Ssam#undef REGISTER 1110167755Ssam 1111167755Ssam return 0; 1112104476Ssam} 1113157205Spjd 1114188154Simpstatic int 1115167755Ssamswcr_detach(device_t dev) 1116157205Spjd{ 1117167755Ssam crypto_unregister_all(swcr_id); 1118157205Spjd if (swcr_sessions != NULL) 1119184205Sdes free(swcr_sessions, M_CRYPTO_DATA); 1120188154Simp return 0; 1121157205Spjd} 1122167755Ssam 1123167755Ssamstatic device_method_t swcr_methods[] = { 1124167755Ssam DEVMETHOD(device_identify, swcr_identify), 1125167755Ssam DEVMETHOD(device_probe, swcr_probe), 1126167755Ssam DEVMETHOD(device_attach, swcr_attach), 1127167755Ssam DEVMETHOD(device_detach, swcr_detach), 1128167755Ssam 1129167755Ssam DEVMETHOD(cryptodev_newsession, swcr_newsession), 1130167755Ssam DEVMETHOD(cryptodev_freesession,swcr_freesession), 1131167755Ssam DEVMETHOD(cryptodev_process, swcr_process), 1132167755Ssam 1133167755Ssam {0, 0}, 1134167755Ssam}; 1135167755Ssam 1136167755Ssamstatic driver_t swcr_driver = { 1137167755Ssam "cryptosoft", 1138167755Ssam swcr_methods, 1139167755Ssam 0, /* NB: no softc */ 1140167755Ssam}; 1141167755Ssamstatic devclass_t swcr_devclass; 1142167755Ssam 1143167755Ssam/* 1144167755Ssam * NB: We explicitly reference the crypto module so we 1145167755Ssam * get the necessary ordering when built as a loadable 1146167755Ssam * module. This is required because we bundle the crypto 1147167755Ssam * module code together with the cryptosoft driver (otherwise 1148167755Ssam * normal module dependencies would handle things). 1149167755Ssam */ 1150167755Ssamextern int crypto_modevent(struct module *, int, void *); 1151167755Ssam/* XXX where to attach */ 1152167755SsamDRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0); 1153167755SsamMODULE_VERSION(cryptosoft, 1); 1154167755SsamMODULE_DEPEND(cryptosoft, crypto, 1, 1, 1); 1155