cryptosoft.c revision 143406
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) 5104476Ssam * 6104476Ssam * This code was written by Angelos D. Keromytis in Athens, Greece, in 7104476Ssam * February 2000. Network Security Technologies Inc. (NSTI) kindly 8104476Ssam * supported the development of this code. 9104476Ssam * 10104476Ssam * Copyright (c) 2000, 2001 Angelos D. Keromytis 11104476Ssam * 12104476Ssam * Permission to use, copy, and modify this software with or without fee 13104476Ssam * is hereby granted, provided that this entire notice is included in 14104476Ssam * all source code copies of any software which is or includes a copy or 15104476Ssam * modification of this software. 16104476Ssam * 17104476Ssam * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 18104476Ssam * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 19104476Ssam * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 20104476Ssam * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 21104476Ssam * PURPOSE. 22104476Ssam */ 23104476Ssam 24116191Sobrien#include <sys/cdefs.h> 25116191Sobrien__FBSDID("$FreeBSD: head/sys/opencrypto/cryptosoft.c 143406 2005-03-11 12:37:07Z ume $"); 26116191Sobrien 27104476Ssam#include <sys/param.h> 28104476Ssam#include <sys/systm.h> 29104476Ssam#include <sys/malloc.h> 30104476Ssam#include <sys/mbuf.h> 31104476Ssam#include <sys/sysctl.h> 32104476Ssam#include <sys/errno.h> 33104476Ssam#include <sys/random.h> 34104476Ssam#include <sys/kernel.h> 35104476Ssam#include <sys/uio.h> 36104476Ssam 37104476Ssam#include <crypto/blowfish/blowfish.h> 38104476Ssam#include <crypto/sha1.h> 39104476Ssam#include <opencrypto/rmd160.h> 40143406Sume#include <opencrypto/cast.h> 41104476Ssam#include <opencrypto/skipjack.h> 42104476Ssam#include <sys/md5.h> 43104476Ssam 44104476Ssam#include <opencrypto/cryptodev.h> 45104476Ssam#include <opencrypto/cryptosoft.h> 46104476Ssam#include <opencrypto/xform.h> 47104476Ssam 48104476Ssamu_int8_t hmac_ipad_buffer[64] = { 49104476Ssam 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 50104476Ssam 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 51104476Ssam 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 52104476Ssam 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 53104476Ssam 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 54104476Ssam 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 55104476Ssam 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 56104476Ssam 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 57104476Ssam}; 58104476Ssam 59104476Ssamu_int8_t hmac_opad_buffer[64] = { 60104476Ssam 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 61104476Ssam 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 62104476Ssam 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 63104476Ssam 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 64104476Ssam 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 65104476Ssam 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 66104476Ssam 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 67104476Ssam 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C 68104476Ssam}; 69104476Ssam 70104476Ssam 71104476Ssamstruct swcr_data **swcr_sessions = NULL; 72104476Ssamu_int32_t swcr_sesnum = 0; 73104476Ssamint32_t swcr_id = -1; 74104476Ssam 75104476Ssam#define COPYBACK(x, a, b, c, d) \ 76104476Ssam (x) == CRYPTO_BUF_MBUF ? m_copyback((struct mbuf *)a,b,c,d) \ 77104476Ssam : cuio_copyback((struct uio *)a,b,c,d) 78104476Ssam#define COPYDATA(x, a, b, c, d) \ 79104476Ssam (x) == CRYPTO_BUF_MBUF ? m_copydata((struct mbuf *)a,b,c,d) \ 80104476Ssam : cuio_copydata((struct uio *)a,b,c,d) 81104476Ssam 82104476Ssamstatic int swcr_encdec(struct cryptodesc *, struct swcr_data *, caddr_t, int); 83104476Ssamstatic int swcr_authcompute(struct cryptop *crp, struct cryptodesc *crd, 84104476Ssam struct swcr_data *sw, caddr_t buf, int outtype); 85104476Ssamstatic int swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int); 86104476Ssamstatic int swcr_process(void *, struct cryptop *, int); 87104476Ssamstatic int swcr_newsession(void *, u_int32_t *, struct cryptoini *); 88104476Ssamstatic int swcr_freesession(void *, u_int64_t); 89104476Ssam 90104476Ssam/* 91104476Ssam * Apply a symmetric encryption/decryption algorithm. 92104476Ssam */ 93104476Ssamstatic int 94104476Ssamswcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf, 95104476Ssam int outtype) 96104476Ssam{ 97104476Ssam unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN], *idat; 98104476Ssam unsigned char *ivp, piv[EALG_MAX_BLOCK_LEN]; 99104476Ssam struct enc_xform *exf; 100104476Ssam int i, k, j, blks; 101104476Ssam 102104476Ssam exf = sw->sw_exf; 103104476Ssam blks = exf->blocksize; 104104476Ssam 105104476Ssam /* Check for non-padded data */ 106104476Ssam if (crd->crd_len % blks) 107104476Ssam return EINVAL; 108104476Ssam 109104476Ssam /* Initialize the IV */ 110104476Ssam if (crd->crd_flags & CRD_F_ENCRYPT) { 111104476Ssam /* IV explicitly provided ? */ 112104476Ssam if (crd->crd_flags & CRD_F_IV_EXPLICIT) 113104476Ssam bcopy(crd->crd_iv, iv, blks); 114104476Ssam else { 115104476Ssam /* Get random IV */ 116104476Ssam for (i = 0; 117104476Ssam i + sizeof (u_int32_t) < EALG_MAX_BLOCK_LEN; 118104476Ssam i += sizeof (u_int32_t)) { 119104476Ssam u_int32_t temp = arc4random(); 120104476Ssam 121104476Ssam bcopy(&temp, iv + i, sizeof(u_int32_t)); 122104476Ssam } 123104476Ssam /* 124104476Ssam * What if the block size is not a multiple 125104476Ssam * of sizeof (u_int32_t), which is the size of 126104476Ssam * what arc4random() returns ? 127104476Ssam */ 128104476Ssam if (EALG_MAX_BLOCK_LEN % sizeof (u_int32_t) != 0) { 129104476Ssam u_int32_t temp = arc4random(); 130104476Ssam 131104476Ssam bcopy (&temp, iv + i, 132104476Ssam EALG_MAX_BLOCK_LEN - i); 133104476Ssam } 134104476Ssam } 135104476Ssam 136104476Ssam /* Do we need to write the IV */ 137104476Ssam if (!(crd->crd_flags & CRD_F_IV_PRESENT)) { 138104476Ssam COPYBACK(outtype, buf, crd->crd_inject, blks, iv); 139104476Ssam } 140104476Ssam 141104476Ssam } else { /* Decryption */ 142104476Ssam /* IV explicitly provided ? */ 143104476Ssam if (crd->crd_flags & CRD_F_IV_EXPLICIT) 144104476Ssam bcopy(crd->crd_iv, iv, blks); 145104476Ssam else { 146104476Ssam /* Get IV off buf */ 147104476Ssam COPYDATA(outtype, buf, crd->crd_inject, blks, iv); 148104476Ssam } 149104476Ssam } 150104476Ssam 151125330Sphk if (crd->crd_flags & CRD_F_KEY_EXPLICIT) { 152125330Sphk int error; 153125330Sphk 154125330Sphk if (sw->sw_kschedule) 155125330Sphk exf->zerokey(&(sw->sw_kschedule)); 156125330Sphk error = exf->setkey(&sw->sw_kschedule, 157125330Sphk crd->crd_key, crd->crd_klen / 8); 158125330Sphk if (error) 159125330Sphk return (error); 160125330Sphk } 161104476Ssam ivp = iv; 162104476Ssam 163104476Ssam if (outtype == CRYPTO_BUF_CONTIG) { 164104476Ssam if (crd->crd_flags & CRD_F_ENCRYPT) { 165104476Ssam for (i = crd->crd_skip; 166104476Ssam i < crd->crd_skip + crd->crd_len; i += blks) { 167104476Ssam /* XOR with the IV/previous block, as appropriate. */ 168104476Ssam if (i == crd->crd_skip) 169104476Ssam for (k = 0; k < blks; k++) 170104476Ssam buf[i + k] ^= ivp[k]; 171104476Ssam else 172104476Ssam for (k = 0; k < blks; k++) 173104476Ssam buf[i + k] ^= buf[i + k - blks]; 174104476Ssam exf->encrypt(sw->sw_kschedule, buf + i); 175104476Ssam } 176104476Ssam } else { /* Decrypt */ 177104476Ssam /* 178104476Ssam * Start at the end, so we don't need to keep the encrypted 179104476Ssam * block as the IV for the next block. 180104476Ssam */ 181104476Ssam for (i = crd->crd_skip + crd->crd_len - blks; 182104476Ssam i >= crd->crd_skip; i -= blks) { 183104476Ssam exf->decrypt(sw->sw_kschedule, buf + i); 184104476Ssam 185104476Ssam /* XOR with the IV/previous block, as appropriate */ 186104476Ssam if (i == crd->crd_skip) 187104476Ssam for (k = 0; k < blks; k++) 188104476Ssam buf[i + k] ^= ivp[k]; 189104476Ssam else 190104476Ssam for (k = 0; k < blks; k++) 191104476Ssam buf[i + k] ^= buf[i + k - blks]; 192104476Ssam } 193104476Ssam } 194104476Ssam 195104476Ssam return 0; 196104476Ssam } else if (outtype == CRYPTO_BUF_MBUF) { 197104476Ssam struct mbuf *m = (struct mbuf *) buf; 198104476Ssam 199104476Ssam /* Find beginning of data */ 200104476Ssam m = m_getptr(m, crd->crd_skip, &k); 201104476Ssam if (m == NULL) 202104476Ssam return EINVAL; 203104476Ssam 204104476Ssam i = crd->crd_len; 205104476Ssam 206104476Ssam while (i > 0) { 207104476Ssam /* 208104476Ssam * If there's insufficient data at the end of 209104476Ssam * an mbuf, we have to do some copying. 210104476Ssam */ 211104476Ssam if (m->m_len < k + blks && m->m_len != k) { 212104476Ssam m_copydata(m, k, blks, blk); 213104476Ssam 214104476Ssam /* Actual encryption/decryption */ 215104476Ssam if (crd->crd_flags & CRD_F_ENCRYPT) { 216104476Ssam /* XOR with previous block */ 217104476Ssam for (j = 0; j < blks; j++) 218104476Ssam blk[j] ^= ivp[j]; 219104476Ssam 220104476Ssam exf->encrypt(sw->sw_kschedule, blk); 221104476Ssam 222104476Ssam /* 223104476Ssam * Keep encrypted block for XOR'ing 224104476Ssam * with next block 225104476Ssam */ 226104476Ssam bcopy(blk, iv, blks); 227104476Ssam ivp = iv; 228104476Ssam } else { /* decrypt */ 229104476Ssam /* 230104476Ssam * Keep encrypted block for XOR'ing 231104476Ssam * with next block 232104476Ssam */ 233104476Ssam if (ivp == iv) 234104476Ssam bcopy(blk, piv, blks); 235104476Ssam else 236104476Ssam bcopy(blk, iv, blks); 237104476Ssam 238104476Ssam exf->decrypt(sw->sw_kschedule, blk); 239104476Ssam 240104476Ssam /* XOR with previous block */ 241104476Ssam for (j = 0; j < blks; j++) 242104476Ssam blk[j] ^= ivp[j]; 243104476Ssam 244104476Ssam if (ivp == iv) 245104476Ssam bcopy(piv, iv, blks); 246104476Ssam else 247104476Ssam ivp = iv; 248104476Ssam } 249104476Ssam 250104476Ssam /* Copy back decrypted block */ 251104476Ssam m_copyback(m, k, blks, blk); 252104476Ssam 253104476Ssam /* Advance pointer */ 254104476Ssam m = m_getptr(m, k + blks, &k); 255104476Ssam if (m == NULL) 256104476Ssam return EINVAL; 257104476Ssam 258104476Ssam i -= blks; 259104476Ssam 260104476Ssam /* Could be done... */ 261104476Ssam if (i == 0) 262104476Ssam break; 263104476Ssam } 264104476Ssam 265104476Ssam /* Skip possibly empty mbufs */ 266104476Ssam if (k == m->m_len) { 267104476Ssam for (m = m->m_next; m && m->m_len == 0; 268104476Ssam m = m->m_next) 269104476Ssam ; 270104476Ssam k = 0; 271104476Ssam } 272104476Ssam 273104476Ssam /* Sanity check */ 274104476Ssam if (m == NULL) 275104476Ssam return EINVAL; 276104476Ssam 277104476Ssam /* 278104476Ssam * Warning: idat may point to garbage here, but 279104476Ssam * we only use it in the while() loop, only if 280104476Ssam * there are indeed enough data. 281104476Ssam */ 282104476Ssam idat = mtod(m, unsigned char *) + k; 283104476Ssam 284104476Ssam while (m->m_len >= k + blks && i > 0) { 285104476Ssam if (crd->crd_flags & CRD_F_ENCRYPT) { 286104476Ssam /* XOR with previous block/IV */ 287104476Ssam for (j = 0; j < blks; j++) 288104476Ssam idat[j] ^= ivp[j]; 289104476Ssam 290104476Ssam exf->encrypt(sw->sw_kschedule, idat); 291104476Ssam ivp = idat; 292104476Ssam } else { /* decrypt */ 293104476Ssam /* 294104476Ssam * Keep encrypted block to be used 295104476Ssam * in next block's processing. 296104476Ssam */ 297104476Ssam if (ivp == iv) 298104476Ssam bcopy(idat, piv, blks); 299104476Ssam else 300104476Ssam bcopy(idat, iv, blks); 301104476Ssam 302104476Ssam exf->decrypt(sw->sw_kschedule, idat); 303104476Ssam 304104476Ssam /* XOR with previous block/IV */ 305104476Ssam for (j = 0; j < blks; j++) 306104476Ssam idat[j] ^= ivp[j]; 307104476Ssam 308104476Ssam if (ivp == iv) 309104476Ssam bcopy(piv, iv, blks); 310104476Ssam else 311104476Ssam ivp = iv; 312104476Ssam } 313104476Ssam 314104476Ssam idat += blks; 315104476Ssam k += blks; 316104476Ssam i -= blks; 317104476Ssam } 318104476Ssam } 319104476Ssam 320104476Ssam return 0; /* Done with mbuf encryption/decryption */ 321104476Ssam } else if (outtype == CRYPTO_BUF_IOV) { 322104476Ssam struct uio *uio = (struct uio *) buf; 323104476Ssam struct iovec *iov; 324104476Ssam 325104476Ssam /* Find beginning of data */ 326104476Ssam iov = cuio_getptr(uio, crd->crd_skip, &k); 327104476Ssam if (iov == NULL) 328104476Ssam return EINVAL; 329104476Ssam 330104476Ssam i = crd->crd_len; 331104476Ssam 332104476Ssam while (i > 0) { 333104476Ssam /* 334104476Ssam * If there's insufficient data at the end of 335104476Ssam * an iovec, we have to do some copying. 336104476Ssam */ 337104476Ssam if (iov->iov_len < k + blks && iov->iov_len != k) { 338104476Ssam cuio_copydata(uio, k, blks, blk); 339104476Ssam 340104476Ssam /* Actual encryption/decryption */ 341104476Ssam if (crd->crd_flags & CRD_F_ENCRYPT) { 342104476Ssam /* XOR with previous block */ 343104476Ssam for (j = 0; j < blks; j++) 344104476Ssam blk[j] ^= ivp[j]; 345104476Ssam 346104476Ssam exf->encrypt(sw->sw_kschedule, blk); 347104476Ssam 348104476Ssam /* 349104476Ssam * Keep encrypted block for XOR'ing 350104476Ssam * with next block 351104476Ssam */ 352104476Ssam bcopy(blk, iv, blks); 353104476Ssam ivp = iv; 354104476Ssam } else { /* decrypt */ 355104476Ssam /* 356104476Ssam * Keep encrypted block for XOR'ing 357104476Ssam * with next block 358104476Ssam */ 359104476Ssam if (ivp == iv) 360104476Ssam bcopy(blk, piv, blks); 361104476Ssam else 362104476Ssam bcopy(blk, iv, blks); 363104476Ssam 364104476Ssam exf->decrypt(sw->sw_kschedule, blk); 365104476Ssam 366104476Ssam /* XOR with previous block */ 367104476Ssam for (j = 0; j < blks; j++) 368104476Ssam blk[j] ^= ivp[j]; 369104476Ssam 370104476Ssam if (ivp == iv) 371104476Ssam bcopy(piv, iv, blks); 372104476Ssam else 373104476Ssam ivp = iv; 374104476Ssam } 375104476Ssam 376104476Ssam /* Copy back decrypted block */ 377104476Ssam cuio_copyback(uio, k, blks, blk); 378104476Ssam 379104476Ssam /* Advance pointer */ 380104476Ssam iov = cuio_getptr(uio, k + blks, &k); 381104476Ssam if (iov == NULL) 382104476Ssam return EINVAL; 383104476Ssam 384104476Ssam i -= blks; 385104476Ssam 386104476Ssam /* Could be done... */ 387104476Ssam if (i == 0) 388104476Ssam break; 389104476Ssam } 390104476Ssam 391104476Ssam /* 392104476Ssam * Warning: idat may point to garbage here, but 393104476Ssam * we only use it in the while() loop, only if 394104476Ssam * there are indeed enough data. 395104476Ssam */ 396104908Smike idat = (char *)iov->iov_base + k; 397104476Ssam 398104476Ssam while (iov->iov_len >= k + blks && i > 0) { 399104476Ssam if (crd->crd_flags & CRD_F_ENCRYPT) { 400104476Ssam /* XOR with previous block/IV */ 401104476Ssam for (j = 0; j < blks; j++) 402104476Ssam idat[j] ^= ivp[j]; 403104476Ssam 404104476Ssam exf->encrypt(sw->sw_kschedule, idat); 405104476Ssam ivp = idat; 406104476Ssam } else { /* decrypt */ 407104476Ssam /* 408104476Ssam * Keep encrypted block to be used 409104476Ssam * in next block's processing. 410104476Ssam */ 411104476Ssam if (ivp == iv) 412104476Ssam bcopy(idat, piv, blks); 413104476Ssam else 414104476Ssam bcopy(idat, iv, blks); 415104476Ssam 416104476Ssam exf->decrypt(sw->sw_kschedule, idat); 417104476Ssam 418104476Ssam /* XOR with previous block/IV */ 419104476Ssam for (j = 0; j < blks; j++) 420104476Ssam idat[j] ^= ivp[j]; 421104476Ssam 422104476Ssam if (ivp == iv) 423104476Ssam bcopy(piv, iv, blks); 424104476Ssam else 425104476Ssam ivp = iv; 426104476Ssam } 427104476Ssam 428104476Ssam idat += blks; 429104476Ssam k += blks; 430104476Ssam i -= blks; 431104476Ssam } 432104476Ssam } 433104476Ssam 434104476Ssam return 0; /* Done with mbuf encryption/decryption */ 435104476Ssam } 436104476Ssam 437104476Ssam /* Unreachable */ 438104476Ssam return EINVAL; 439104476Ssam} 440104476Ssam 441104476Ssam/* 442104476Ssam * Compute keyed-hash authenticator. 443104476Ssam */ 444104476Ssamstatic int 445104476Ssamswcr_authcompute(struct cryptop *crp, struct cryptodesc *crd, 446104476Ssam struct swcr_data *sw, caddr_t buf, int outtype) 447104476Ssam{ 448104476Ssam unsigned char aalg[AALG_MAX_RESULT_LEN]; 449104476Ssam struct auth_hash *axf; 450104476Ssam union authctx ctx; 451104476Ssam int err; 452104476Ssam 453104476Ssam if (sw->sw_ictx == 0) 454104476Ssam return EINVAL; 455104476Ssam 456104476Ssam axf = sw->sw_axf; 457104476Ssam 458104476Ssam bcopy(sw->sw_ictx, &ctx, axf->ctxsize); 459104476Ssam 460104476Ssam switch (outtype) { 461104476Ssam case CRYPTO_BUF_CONTIG: 462104476Ssam axf->Update(&ctx, buf + crd->crd_skip, crd->crd_len); 463104476Ssam break; 464104476Ssam case CRYPTO_BUF_MBUF: 465104476Ssam err = m_apply((struct mbuf *) buf, crd->crd_skip, crd->crd_len, 466123564Sbms (int (*)(void *, void *, unsigned int)) axf->Update, 467104476Ssam (caddr_t) &ctx); 468104476Ssam if (err) 469104476Ssam return err; 470104476Ssam break; 471104476Ssam case CRYPTO_BUF_IOV: 472104476Ssam default: 473104476Ssam return EINVAL; 474104476Ssam } 475104476Ssam 476104476Ssam switch (sw->sw_alg) { 477104476Ssam case CRYPTO_MD5_HMAC: 478104476Ssam case CRYPTO_SHA1_HMAC: 479104476Ssam case CRYPTO_SHA2_HMAC: 480104476Ssam case CRYPTO_RIPEMD160_HMAC: 481104476Ssam if (sw->sw_octx == NULL) 482104476Ssam return EINVAL; 483104476Ssam 484104476Ssam axf->Final(aalg, &ctx); 485104476Ssam bcopy(sw->sw_octx, &ctx, axf->ctxsize); 486104476Ssam axf->Update(&ctx, aalg, axf->hashsize); 487104476Ssam axf->Final(aalg, &ctx); 488104476Ssam break; 489104476Ssam 490104476Ssam case CRYPTO_MD5_KPDK: 491104476Ssam case CRYPTO_SHA1_KPDK: 492104476Ssam if (sw->sw_octx == NULL) 493104476Ssam return EINVAL; 494104476Ssam 495104476Ssam axf->Update(&ctx, sw->sw_octx, sw->sw_klen); 496104476Ssam axf->Final(aalg, &ctx); 497104476Ssam break; 498104476Ssam 499104476Ssam case CRYPTO_NULL_HMAC: 500104476Ssam axf->Final(aalg, &ctx); 501104476Ssam break; 502104476Ssam } 503104476Ssam 504104476Ssam /* Inject the authentication data */ 505104476Ssam if (outtype == CRYPTO_BUF_CONTIG) 506104476Ssam bcopy(aalg, buf + crd->crd_inject, axf->authsize); 507104476Ssam else 508104476Ssam m_copyback((struct mbuf *) buf, crd->crd_inject, 509104476Ssam axf->authsize, aalg); 510104476Ssam return 0; 511104476Ssam} 512104476Ssam 513104476Ssam/* 514104476Ssam * Apply a compression/decompression algorithm 515104476Ssam */ 516104476Ssamstatic int 517104476Ssamswcr_compdec(struct cryptodesc *crd, struct swcr_data *sw, 518104476Ssam caddr_t buf, int outtype) 519104476Ssam{ 520104476Ssam u_int8_t *data, *out; 521104476Ssam struct comp_algo *cxf; 522104476Ssam int adj; 523104476Ssam u_int32_t result; 524104476Ssam 525104476Ssam cxf = sw->sw_cxf; 526104476Ssam 527104476Ssam /* We must handle the whole buffer of data in one time 528104476Ssam * then if there is not all the data in the mbuf, we must 529104476Ssam * copy in a buffer. 530104476Ssam */ 531104476Ssam 532104476Ssam MALLOC(data, u_int8_t *, crd->crd_len, M_CRYPTO_DATA, M_NOWAIT); 533104476Ssam if (data == NULL) 534104476Ssam return (EINVAL); 535104476Ssam COPYDATA(outtype, buf, crd->crd_skip, crd->crd_len, data); 536104476Ssam 537104476Ssam if (crd->crd_flags & CRD_F_COMP) 538104476Ssam result = cxf->compress(data, crd->crd_len, &out); 539104476Ssam else 540104476Ssam result = cxf->decompress(data, crd->crd_len, &out); 541104476Ssam 542104476Ssam FREE(data, M_CRYPTO_DATA); 543104476Ssam if (result == 0) 544104476Ssam return EINVAL; 545104476Ssam 546104476Ssam /* Copy back the (de)compressed data. m_copyback is 547104476Ssam * extending the mbuf as necessary. 548104476Ssam */ 549104476Ssam sw->sw_size = result; 550104476Ssam /* Check the compressed size when doing compression */ 551104476Ssam if (crd->crd_flags & CRD_F_COMP) { 552104476Ssam if (result > crd->crd_len) { 553104476Ssam /* Compression was useless, we lost time */ 554104476Ssam FREE(out, M_CRYPTO_DATA); 555104476Ssam return 0; 556104476Ssam } 557104476Ssam } 558104476Ssam 559104476Ssam COPYBACK(outtype, buf, crd->crd_skip, result, out); 560104476Ssam if (result < crd->crd_len) { 561104476Ssam adj = result - crd->crd_len; 562104476Ssam if (outtype == CRYPTO_BUF_MBUF) { 563104476Ssam adj = result - crd->crd_len; 564104476Ssam m_adj((struct mbuf *)buf, adj); 565104476Ssam } else { 566104476Ssam struct uio *uio = (struct uio *)buf; 567104476Ssam int ind; 568104476Ssam 569104476Ssam adj = crd->crd_len - result; 570104476Ssam ind = uio->uio_iovcnt - 1; 571104476Ssam 572104476Ssam while (adj > 0 && ind >= 0) { 573104476Ssam if (adj < uio->uio_iov[ind].iov_len) { 574104476Ssam uio->uio_iov[ind].iov_len -= adj; 575104476Ssam break; 576104476Ssam } 577104476Ssam 578104476Ssam adj -= uio->uio_iov[ind].iov_len; 579104476Ssam uio->uio_iov[ind].iov_len = 0; 580104476Ssam ind--; 581104476Ssam uio->uio_iovcnt--; 582104476Ssam } 583104476Ssam } 584104476Ssam } 585104476Ssam FREE(out, M_CRYPTO_DATA); 586104476Ssam return 0; 587104476Ssam} 588104476Ssam 589104476Ssam/* 590104476Ssam * Generate a new software session. 591104476Ssam */ 592104476Ssamstatic int 593104476Ssamswcr_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri) 594104476Ssam{ 595104476Ssam struct swcr_data **swd; 596104476Ssam struct auth_hash *axf; 597104476Ssam struct enc_xform *txf; 598104476Ssam struct comp_algo *cxf; 599104476Ssam u_int32_t i; 600104476Ssam int k, error; 601104476Ssam 602104476Ssam if (sid == NULL || cri == NULL) 603104476Ssam return EINVAL; 604104476Ssam 605104476Ssam if (swcr_sessions) { 606104476Ssam for (i = 1; i < swcr_sesnum; i++) 607104476Ssam if (swcr_sessions[i] == NULL) 608104476Ssam break; 609104476Ssam } else 610104476Ssam i = 1; /* NB: to silence compiler warning */ 611104476Ssam 612104476Ssam if (swcr_sessions == NULL || i == swcr_sesnum) { 613104476Ssam if (swcr_sessions == NULL) { 614104476Ssam i = 1; /* We leave swcr_sessions[0] empty */ 615104476Ssam swcr_sesnum = CRYPTO_SW_SESSIONS; 616104476Ssam } else 617104476Ssam swcr_sesnum *= 2; 618104476Ssam 619104476Ssam swd = malloc(swcr_sesnum * sizeof(struct swcr_data *), 620104476Ssam M_CRYPTO_DATA, M_NOWAIT|M_ZERO); 621104476Ssam if (swd == NULL) { 622104476Ssam /* Reset session number */ 623104476Ssam if (swcr_sesnum == CRYPTO_SW_SESSIONS) 624104476Ssam swcr_sesnum = 0; 625104476Ssam else 626104476Ssam swcr_sesnum /= 2; 627104476Ssam return ENOBUFS; 628104476Ssam } 629104476Ssam 630104476Ssam /* Copy existing sessions */ 631104476Ssam if (swcr_sessions) { 632104476Ssam bcopy(swcr_sessions, swd, 633104476Ssam (swcr_sesnum / 2) * sizeof(struct swcr_data *)); 634104476Ssam free(swcr_sessions, M_CRYPTO_DATA); 635104476Ssam } 636104476Ssam 637104476Ssam swcr_sessions = swd; 638104476Ssam } 639104476Ssam 640104476Ssam swd = &swcr_sessions[i]; 641104476Ssam *sid = i; 642104476Ssam 643104476Ssam while (cri) { 644104476Ssam MALLOC(*swd, struct swcr_data *, sizeof(struct swcr_data), 645104476Ssam M_CRYPTO_DATA, M_NOWAIT|M_ZERO); 646104476Ssam if (*swd == NULL) { 647104476Ssam swcr_freesession(NULL, i); 648104476Ssam return ENOBUFS; 649104476Ssam } 650104476Ssam 651104476Ssam switch (cri->cri_alg) { 652104476Ssam case CRYPTO_DES_CBC: 653104476Ssam txf = &enc_xform_des; 654104476Ssam goto enccommon; 655104476Ssam case CRYPTO_3DES_CBC: 656104476Ssam txf = &enc_xform_3des; 657104476Ssam goto enccommon; 658104476Ssam case CRYPTO_BLF_CBC: 659104476Ssam txf = &enc_xform_blf; 660104476Ssam goto enccommon; 661104476Ssam case CRYPTO_CAST_CBC: 662104476Ssam txf = &enc_xform_cast5; 663104476Ssam goto enccommon; 664104476Ssam case CRYPTO_SKIPJACK_CBC: 665104476Ssam txf = &enc_xform_skipjack; 666104476Ssam goto enccommon; 667104476Ssam case CRYPTO_RIJNDAEL128_CBC: 668104476Ssam txf = &enc_xform_rijndael128; 669104476Ssam goto enccommon; 670104476Ssam case CRYPTO_NULL_CBC: 671104476Ssam txf = &enc_xform_null; 672104476Ssam goto enccommon; 673104476Ssam enccommon: 674104476Ssam error = txf->setkey(&((*swd)->sw_kschedule), 675104476Ssam cri->cri_key, cri->cri_klen / 8); 676104476Ssam if (error) { 677104476Ssam swcr_freesession(NULL, i); 678104476Ssam return error; 679104476Ssam } 680104476Ssam (*swd)->sw_exf = txf; 681104476Ssam break; 682104476Ssam 683104476Ssam case CRYPTO_MD5_HMAC: 684104476Ssam axf = &auth_hash_hmac_md5_96; 685104476Ssam goto authcommon; 686104476Ssam case CRYPTO_SHA1_HMAC: 687104476Ssam axf = &auth_hash_hmac_sha1_96; 688104476Ssam goto authcommon; 689104476Ssam case CRYPTO_SHA2_HMAC: 690104476Ssam if (cri->cri_klen == 256) 691104476Ssam axf = &auth_hash_hmac_sha2_256; 692104476Ssam else if (cri->cri_klen == 384) 693104476Ssam axf = &auth_hash_hmac_sha2_384; 694104476Ssam else if (cri->cri_klen == 512) 695104476Ssam axf = &auth_hash_hmac_sha2_512; 696104476Ssam else { 697104476Ssam swcr_freesession(NULL, i); 698104476Ssam return EINVAL; 699104476Ssam } 700104476Ssam goto authcommon; 701104476Ssam case CRYPTO_NULL_HMAC: 702104476Ssam axf = &auth_hash_null; 703104476Ssam goto authcommon; 704104476Ssam case CRYPTO_RIPEMD160_HMAC: 705104476Ssam axf = &auth_hash_hmac_ripemd_160_96; 706104476Ssam authcommon: 707104476Ssam (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 708104476Ssam M_NOWAIT); 709104476Ssam if ((*swd)->sw_ictx == NULL) { 710104476Ssam swcr_freesession(NULL, i); 711104476Ssam return ENOBUFS; 712104476Ssam } 713104476Ssam 714104476Ssam (*swd)->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA, 715104476Ssam M_NOWAIT); 716104476Ssam if ((*swd)->sw_octx == NULL) { 717104476Ssam swcr_freesession(NULL, i); 718104476Ssam return ENOBUFS; 719104476Ssam } 720104476Ssam 721104476Ssam for (k = 0; k < cri->cri_klen / 8; k++) 722104476Ssam cri->cri_key[k] ^= HMAC_IPAD_VAL; 723104476Ssam 724104476Ssam axf->Init((*swd)->sw_ictx); 725104476Ssam axf->Update((*swd)->sw_ictx, cri->cri_key, 726104476Ssam cri->cri_klen / 8); 727104476Ssam axf->Update((*swd)->sw_ictx, hmac_ipad_buffer, 728104476Ssam HMAC_BLOCK_LEN - (cri->cri_klen / 8)); 729104476Ssam 730104476Ssam for (k = 0; k < cri->cri_klen / 8; k++) 731104476Ssam cri->cri_key[k] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); 732104476Ssam 733104476Ssam axf->Init((*swd)->sw_octx); 734104476Ssam axf->Update((*swd)->sw_octx, cri->cri_key, 735104476Ssam cri->cri_klen / 8); 736104476Ssam axf->Update((*swd)->sw_octx, hmac_opad_buffer, 737104476Ssam HMAC_BLOCK_LEN - (cri->cri_klen / 8)); 738104476Ssam 739104476Ssam for (k = 0; k < cri->cri_klen / 8; k++) 740104476Ssam cri->cri_key[k] ^= HMAC_OPAD_VAL; 741104476Ssam (*swd)->sw_axf = axf; 742104476Ssam break; 743104476Ssam 744104476Ssam case CRYPTO_MD5_KPDK: 745104476Ssam axf = &auth_hash_key_md5; 746104476Ssam goto auth2common; 747104476Ssam 748104476Ssam case CRYPTO_SHA1_KPDK: 749104476Ssam axf = &auth_hash_key_sha1; 750104476Ssam auth2common: 751104476Ssam (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 752104476Ssam M_NOWAIT); 753104476Ssam if ((*swd)->sw_ictx == NULL) { 754104476Ssam swcr_freesession(NULL, i); 755104476Ssam return ENOBUFS; 756104476Ssam } 757104476Ssam 758104476Ssam /* Store the key so we can "append" it to the payload */ 759104476Ssam (*swd)->sw_octx = malloc(cri->cri_klen / 8, M_CRYPTO_DATA, 760104476Ssam M_NOWAIT); 761104476Ssam if ((*swd)->sw_octx == NULL) { 762104476Ssam swcr_freesession(NULL, i); 763104476Ssam return ENOBUFS; 764104476Ssam } 765104476Ssam 766104476Ssam (*swd)->sw_klen = cri->cri_klen / 8; 767104476Ssam bcopy(cri->cri_key, (*swd)->sw_octx, cri->cri_klen / 8); 768104476Ssam axf->Init((*swd)->sw_ictx); 769104476Ssam axf->Update((*swd)->sw_ictx, cri->cri_key, 770104476Ssam cri->cri_klen / 8); 771104476Ssam axf->Final(NULL, (*swd)->sw_ictx); 772104476Ssam (*swd)->sw_axf = axf; 773104476Ssam break; 774104476Ssam#ifdef notdef 775104476Ssam case CRYPTO_MD5: 776104476Ssam axf = &auth_hash_md5; 777104476Ssam goto auth3common; 778104476Ssam 779104476Ssam case CRYPTO_SHA1: 780104476Ssam axf = &auth_hash_sha1; 781104476Ssam auth3common: 782104476Ssam (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 783104476Ssam M_NOWAIT); 784104476Ssam if ((*swd)->sw_ictx == NULL) { 785104476Ssam swcr_freesession(NULL, i); 786104476Ssam return ENOBUFS; 787104476Ssam } 788104476Ssam 789104476Ssam axf->Init((*swd)->sw_ictx); 790104476Ssam (*swd)->sw_axf = axf; 791104476Ssam break; 792104476Ssam#endif 793104476Ssam case CRYPTO_DEFLATE_COMP: 794104476Ssam cxf = &comp_algo_deflate; 795104476Ssam (*swd)->sw_cxf = cxf; 796104476Ssam break; 797104476Ssam default: 798104476Ssam swcr_freesession(NULL, i); 799104476Ssam return EINVAL; 800104476Ssam } 801104476Ssam 802104476Ssam (*swd)->sw_alg = cri->cri_alg; 803104476Ssam cri = cri->cri_next; 804104476Ssam swd = &((*swd)->sw_next); 805104476Ssam } 806104476Ssam return 0; 807104476Ssam} 808104476Ssam 809104476Ssam/* 810104476Ssam * Free a session. 811104476Ssam */ 812104476Ssamstatic int 813104476Ssamswcr_freesession(void *arg, u_int64_t tid) 814104476Ssam{ 815104476Ssam struct swcr_data *swd; 816104476Ssam struct enc_xform *txf; 817104476Ssam struct auth_hash *axf; 818104476Ssam struct comp_algo *cxf; 819116924Ssam u_int32_t sid = CRYPTO_SESID2LID(tid); 820104476Ssam 821104476Ssam if (sid > swcr_sesnum || swcr_sessions == NULL || 822104476Ssam swcr_sessions[sid] == NULL) 823104476Ssam return EINVAL; 824104476Ssam 825104476Ssam /* Silently accept and return */ 826104476Ssam if (sid == 0) 827104476Ssam return 0; 828104476Ssam 829104476Ssam while ((swd = swcr_sessions[sid]) != NULL) { 830104476Ssam swcr_sessions[sid] = swd->sw_next; 831104476Ssam 832104476Ssam switch (swd->sw_alg) { 833104476Ssam case CRYPTO_DES_CBC: 834104476Ssam case CRYPTO_3DES_CBC: 835104476Ssam case CRYPTO_BLF_CBC: 836104476Ssam case CRYPTO_CAST_CBC: 837104476Ssam case CRYPTO_SKIPJACK_CBC: 838104476Ssam case CRYPTO_RIJNDAEL128_CBC: 839104476Ssam case CRYPTO_NULL_CBC: 840104476Ssam txf = swd->sw_exf; 841104476Ssam 842104476Ssam if (swd->sw_kschedule) 843104476Ssam txf->zerokey(&(swd->sw_kschedule)); 844104476Ssam break; 845104476Ssam 846104476Ssam case CRYPTO_MD5_HMAC: 847104476Ssam case CRYPTO_SHA1_HMAC: 848104476Ssam case CRYPTO_SHA2_HMAC: 849104476Ssam case CRYPTO_RIPEMD160_HMAC: 850104476Ssam case CRYPTO_NULL_HMAC: 851104476Ssam axf = swd->sw_axf; 852104476Ssam 853104476Ssam if (swd->sw_ictx) { 854104476Ssam bzero(swd->sw_ictx, axf->ctxsize); 855104476Ssam free(swd->sw_ictx, M_CRYPTO_DATA); 856104476Ssam } 857104476Ssam if (swd->sw_octx) { 858104476Ssam bzero(swd->sw_octx, axf->ctxsize); 859104476Ssam free(swd->sw_octx, M_CRYPTO_DATA); 860104476Ssam } 861104476Ssam break; 862104476Ssam 863104476Ssam case CRYPTO_MD5_KPDK: 864104476Ssam case CRYPTO_SHA1_KPDK: 865104476Ssam axf = swd->sw_axf; 866104476Ssam 867104476Ssam if (swd->sw_ictx) { 868104476Ssam bzero(swd->sw_ictx, axf->ctxsize); 869104476Ssam free(swd->sw_ictx, M_CRYPTO_DATA); 870104476Ssam } 871104476Ssam if (swd->sw_octx) { 872104476Ssam bzero(swd->sw_octx, swd->sw_klen); 873104476Ssam free(swd->sw_octx, M_CRYPTO_DATA); 874104476Ssam } 875104476Ssam break; 876104476Ssam 877104476Ssam case CRYPTO_MD5: 878104476Ssam case CRYPTO_SHA1: 879104476Ssam axf = swd->sw_axf; 880104476Ssam 881104476Ssam if (swd->sw_ictx) 882104476Ssam free(swd->sw_ictx, M_CRYPTO_DATA); 883104476Ssam break; 884104476Ssam 885104476Ssam case CRYPTO_DEFLATE_COMP: 886104476Ssam cxf = swd->sw_cxf; 887104476Ssam break; 888104476Ssam } 889104476Ssam 890104476Ssam FREE(swd, M_CRYPTO_DATA); 891104476Ssam } 892104476Ssam return 0; 893104476Ssam} 894104476Ssam 895104476Ssam/* 896104476Ssam * Process a software request. 897104476Ssam */ 898104476Ssamstatic int 899104476Ssamswcr_process(void *arg, struct cryptop *crp, int hint) 900104476Ssam{ 901104476Ssam struct cryptodesc *crd; 902104476Ssam struct swcr_data *sw; 903104476Ssam u_int32_t lid; 904104476Ssam int type; 905104476Ssam 906104476Ssam /* Sanity check */ 907104476Ssam if (crp == NULL) 908104476Ssam return EINVAL; 909104476Ssam 910104476Ssam if (crp->crp_desc == NULL || crp->crp_buf == NULL) { 911104476Ssam crp->crp_etype = EINVAL; 912104476Ssam goto done; 913104476Ssam } 914104476Ssam 915104476Ssam lid = crp->crp_sid & 0xffffffff; 916104476Ssam if (lid >= swcr_sesnum || lid == 0 || swcr_sessions[lid] == NULL) { 917104476Ssam crp->crp_etype = ENOENT; 918104476Ssam goto done; 919104476Ssam } 920104476Ssam 921104476Ssam if (crp->crp_flags & CRYPTO_F_IMBUF) { 922104476Ssam type = CRYPTO_BUF_MBUF; 923104476Ssam } else if (crp->crp_flags & CRYPTO_F_IOV) { 924104476Ssam type = CRYPTO_BUF_IOV; 925104476Ssam } else { 926104476Ssam type = CRYPTO_BUF_CONTIG; 927104476Ssam } 928104476Ssam 929104476Ssam /* Go through crypto descriptors, processing as we go */ 930104476Ssam for (crd = crp->crp_desc; crd; crd = crd->crd_next) { 931104476Ssam /* 932104476Ssam * Find the crypto context. 933104476Ssam * 934104476Ssam * XXX Note that the logic here prevents us from having 935104476Ssam * XXX the same algorithm multiple times in a session 936104476Ssam * XXX (or rather, we can but it won't give us the right 937104476Ssam * XXX results). To do that, we'd need some way of differentiating 938104476Ssam * XXX between the various instances of an algorithm (so we can 939104476Ssam * XXX locate the correct crypto context). 940104476Ssam */ 941104476Ssam for (sw = swcr_sessions[lid]; 942104476Ssam sw && sw->sw_alg != crd->crd_alg; 943104476Ssam sw = sw->sw_next) 944104476Ssam ; 945104476Ssam 946104476Ssam /* No such context ? */ 947104476Ssam if (sw == NULL) { 948104476Ssam crp->crp_etype = EINVAL; 949104476Ssam goto done; 950104476Ssam } 951104476Ssam switch (sw->sw_alg) { 952104476Ssam case CRYPTO_DES_CBC: 953104476Ssam case CRYPTO_3DES_CBC: 954104476Ssam case CRYPTO_BLF_CBC: 955104476Ssam case CRYPTO_CAST_CBC: 956104476Ssam case CRYPTO_SKIPJACK_CBC: 957104476Ssam case CRYPTO_RIJNDAEL128_CBC: 958104476Ssam if ((crp->crp_etype = swcr_encdec(crd, sw, 959104476Ssam crp->crp_buf, type)) != 0) 960104476Ssam goto done; 961104476Ssam break; 962104476Ssam case CRYPTO_NULL_CBC: 963104476Ssam crp->crp_etype = 0; 964104476Ssam break; 965104476Ssam case CRYPTO_MD5_HMAC: 966104476Ssam case CRYPTO_SHA1_HMAC: 967104476Ssam case CRYPTO_SHA2_HMAC: 968104476Ssam case CRYPTO_RIPEMD160_HMAC: 969104476Ssam case CRYPTO_NULL_HMAC: 970104476Ssam case CRYPTO_MD5_KPDK: 971104476Ssam case CRYPTO_SHA1_KPDK: 972104476Ssam case CRYPTO_MD5: 973104476Ssam case CRYPTO_SHA1: 974104476Ssam if ((crp->crp_etype = swcr_authcompute(crp, crd, sw, 975104476Ssam crp->crp_buf, type)) != 0) 976104476Ssam goto done; 977104476Ssam break; 978104476Ssam 979104476Ssam case CRYPTO_DEFLATE_COMP: 980104476Ssam if ((crp->crp_etype = swcr_compdec(crd, sw, 981104476Ssam crp->crp_buf, type)) != 0) 982104476Ssam goto done; 983104476Ssam else 984104476Ssam crp->crp_olen = (int)sw->sw_size; 985104476Ssam break; 986104476Ssam 987104476Ssam default: 988104476Ssam /* Unknown/unsupported algorithm */ 989104476Ssam crp->crp_etype = EINVAL; 990104476Ssam goto done; 991104476Ssam } 992104476Ssam } 993104476Ssam 994104476Ssamdone: 995104476Ssam crypto_done(crp); 996104476Ssam return 0; 997104476Ssam} 998104476Ssam 999104476Ssam/* 1000104476Ssam * Initialize the driver, called from the kernel main(). 1001104476Ssam */ 1002104476Ssamstatic void 1003104476Ssamswcr_init(void) 1004104476Ssam{ 1005116924Ssam swcr_id = crypto_get_driverid(CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC); 1006104476Ssam if (swcr_id < 0) 1007104476Ssam panic("Software crypto device cannot initialize!"); 1008104476Ssam crypto_register(swcr_id, CRYPTO_DES_CBC, 1009104476Ssam 0, 0, swcr_newsession, swcr_freesession, swcr_process, NULL); 1010104476Ssam#define REGISTER(alg) \ 1011104476Ssam crypto_register(swcr_id, alg, 0,0,NULL,NULL,NULL,NULL) 1012104476Ssam REGISTER(CRYPTO_3DES_CBC); 1013104476Ssam REGISTER(CRYPTO_BLF_CBC); 1014104476Ssam REGISTER(CRYPTO_CAST_CBC); 1015104476Ssam REGISTER(CRYPTO_SKIPJACK_CBC); 1016104476Ssam REGISTER(CRYPTO_NULL_CBC); 1017104476Ssam REGISTER(CRYPTO_MD5_HMAC); 1018104476Ssam REGISTER(CRYPTO_SHA1_HMAC); 1019104476Ssam REGISTER(CRYPTO_SHA2_HMAC); 1020104476Ssam REGISTER(CRYPTO_RIPEMD160_HMAC); 1021104476Ssam REGISTER(CRYPTO_NULL_HMAC); 1022104476Ssam REGISTER(CRYPTO_MD5_KPDK); 1023104476Ssam REGISTER(CRYPTO_SHA1_KPDK); 1024104476Ssam REGISTER(CRYPTO_MD5); 1025104476Ssam REGISTER(CRYPTO_SHA1); 1026104476Ssam REGISTER(CRYPTO_RIJNDAEL128_CBC); 1027104476Ssam REGISTER(CRYPTO_DEFLATE_COMP); 1028104476Ssam#undef REGISTER 1029104476Ssam} 1030104476SsamSYSINIT(cryptosoft_init, SI_SUB_PSEUDO, SI_ORDER_ANY, swcr_init, NULL) 1031