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