Annotation of sys/crypto/cryptosoft.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: cryptosoft.c,v 1.46 2006/12/29 13:04:37 pedro Exp $ */
! 2:
! 3: /*
! 4: * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
! 5: *
! 6: * This code was written by Angelos D. Keromytis in Athens, Greece, in
! 7: * February 2000. Network Security Technologies Inc. (NSTI) kindly
! 8: * supported the development of this code.
! 9: *
! 10: * Copyright (c) 2000, 2001 Angelos D. Keromytis
! 11: *
! 12: * Permission to use, copy, and modify this software with or without fee
! 13: * is hereby granted, provided that this entire notice is included in
! 14: * all source code copies of any software which is or includes a copy or
! 15: * modification of this software.
! 16: *
! 17: * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
! 18: * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
! 19: * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
! 20: * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
! 21: * PURPOSE.
! 22: */
! 23:
! 24: #include <sys/param.h>
! 25: #include <sys/systm.h>
! 26: #include <sys/malloc.h>
! 27: #include <sys/mbuf.h>
! 28: #include <sys/sysctl.h>
! 29: #include <sys/errno.h>
! 30: #include <dev/rndvar.h>
! 31: #include <crypto/md5.h>
! 32: #include <crypto/sha1.h>
! 33: #include <crypto/rmd160.h>
! 34: #include <crypto/cast.h>
! 35: #include <crypto/skipjack.h>
! 36: #include <crypto/blf.h>
! 37: #include <crypto/cryptodev.h>
! 38: #include <crypto/cryptosoft.h>
! 39: #include <crypto/xform.h>
! 40:
! 41: u_int8_t hmac_ipad_buffer[64] = {
! 42: 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
! 43: 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
! 44: 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
! 45: 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
! 46: 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
! 47: 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
! 48: 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
! 49: 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
! 50: };
! 51:
! 52: u_int8_t hmac_opad_buffer[64] = {
! 53: 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
! 54: 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
! 55: 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
! 56: 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
! 57: 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
! 58: 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
! 59: 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
! 60: 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C
! 61: };
! 62:
! 63:
! 64: struct swcr_data **swcr_sessions = NULL;
! 65: u_int32_t swcr_sesnum = 0;
! 66: int32_t swcr_id = -1;
! 67:
! 68: #define COPYBACK(x, a, b, c, d) \
! 69: (x) == CRYPTO_BUF_MBUF ? m_copyback((struct mbuf *)a,b,c,d) \
! 70: : cuio_copyback((struct uio *)a,b,c,d)
! 71: #define COPYDATA(x, a, b, c, d) \
! 72: (x) == CRYPTO_BUF_MBUF ? m_copydata((struct mbuf *)a,b,c,d) \
! 73: : cuio_copydata((struct uio *)a,b,c,d)
! 74:
! 75: /*
! 76: * Apply a symmetric encryption/decryption algorithm.
! 77: */
! 78: int
! 79: swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
! 80: int outtype)
! 81: {
! 82: unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN], *idat;
! 83: unsigned char *ivp, piv[EALG_MAX_BLOCK_LEN];
! 84: struct enc_xform *exf;
! 85: int i, k, j, blks, ind, count, ivlen;
! 86: struct mbuf *m = NULL;
! 87: struct uio *uio = NULL;
! 88:
! 89: exf = sw->sw_exf;
! 90: blks = exf->blocksize;
! 91: ivlen = exf->ivsize;
! 92:
! 93: /* Check for non-padded data */
! 94: if (crd->crd_len % blks)
! 95: return EINVAL;
! 96:
! 97: if (outtype == CRYPTO_BUF_MBUF)
! 98: m = (struct mbuf *) buf;
! 99: else
! 100: uio = (struct uio *) buf;
! 101:
! 102: /* Initialize the IV */
! 103: if (crd->crd_flags & CRD_F_ENCRYPT) {
! 104: /* IV explicitly provided ? */
! 105: if (crd->crd_flags & CRD_F_IV_EXPLICIT)
! 106: bcopy(crd->crd_iv, iv, ivlen);
! 107: else
! 108: arc4random_bytes(iv, ivlen);
! 109:
! 110: /* Do we need to write the IV */
! 111: if (!(crd->crd_flags & CRD_F_IV_PRESENT)) {
! 112: COPYBACK(outtype, buf, crd->crd_inject, ivlen, iv);
! 113: }
! 114:
! 115: } else { /* Decryption */
! 116: /* IV explicitly provided ? */
! 117: if (crd->crd_flags & CRD_F_IV_EXPLICIT)
! 118: bcopy(crd->crd_iv, iv, ivlen);
! 119: else {
! 120: /* Get IV off buf */
! 121: COPYDATA(outtype, buf, crd->crd_inject, ivlen, iv);
! 122: }
! 123: }
! 124:
! 125: ivp = iv;
! 126:
! 127: if (exf->reinit)
! 128: exf->reinit(sw->sw_kschedule, iv);
! 129:
! 130: if (outtype == CRYPTO_BUF_MBUF) {
! 131: /* Find beginning of data */
! 132: m = m_getptr(m, crd->crd_skip, &k);
! 133: if (m == NULL)
! 134: return EINVAL;
! 135:
! 136: i = crd->crd_len;
! 137:
! 138: while (i > 0) {
! 139: /*
! 140: * If there's insufficient data at the end of
! 141: * an mbuf, we have to do some copying.
! 142: */
! 143: if (m->m_len < k + blks && m->m_len != k) {
! 144: m_copydata(m, k, blks, blk);
! 145:
! 146: /* Actual encryption/decryption */
! 147: if (exf->reinit) {
! 148: exf->encrypt(sw->sw_kschedule, blk);
! 149: } else if (crd->crd_flags & CRD_F_ENCRYPT) {
! 150: /* XOR with previous block */
! 151: for (j = 0; j < blks; j++)
! 152: blk[j] ^= ivp[j];
! 153:
! 154: exf->encrypt(sw->sw_kschedule, blk);
! 155:
! 156: /*
! 157: * Keep encrypted block for XOR'ing
! 158: * with next block
! 159: */
! 160: bcopy(blk, iv, blks);
! 161: ivp = iv;
! 162: } else { /* decrypt */
! 163: /*
! 164: * Keep encrypted block for XOR'ing
! 165: * with next block
! 166: */
! 167: if (ivp == iv)
! 168: bcopy(blk, piv, blks);
! 169: else
! 170: bcopy(blk, iv, blks);
! 171:
! 172: exf->decrypt(sw->sw_kschedule, blk);
! 173:
! 174: /* XOR with previous block */
! 175: for (j = 0; j < blks; j++)
! 176: blk[j] ^= ivp[j];
! 177:
! 178: if (ivp == iv)
! 179: bcopy(piv, iv, blks);
! 180: else
! 181: ivp = iv;
! 182: }
! 183:
! 184: /* Copy back decrypted block */
! 185: m_copyback(m, k, blks, blk);
! 186:
! 187: /* Advance pointer */
! 188: m = m_getptr(m, k + blks, &k);
! 189: if (m == NULL)
! 190: return EINVAL;
! 191:
! 192: i -= blks;
! 193:
! 194: /* Could be done... */
! 195: if (i == 0)
! 196: break;
! 197: }
! 198:
! 199: /* Skip possibly empty mbufs */
! 200: if (k == m->m_len) {
! 201: for (m = m->m_next; m && m->m_len == 0;
! 202: m = m->m_next)
! 203: ;
! 204: k = 0;
! 205: }
! 206:
! 207: /* Sanity check */
! 208: if (m == NULL)
! 209: return EINVAL;
! 210:
! 211: /*
! 212: * Warning: idat may point to garbage here, but
! 213: * we only use it in the while() loop, only if
! 214: * there are indeed enough data.
! 215: */
! 216: idat = mtod(m, unsigned char *) + k;
! 217:
! 218: while (m->m_len >= k + blks && i > 0) {
! 219: if (exf->reinit) {
! 220: exf->encrypt(sw->sw_kschedule, idat);
! 221: } else if (crd->crd_flags & CRD_F_ENCRYPT) {
! 222: /* XOR with previous block/IV */
! 223: for (j = 0; j < blks; j++)
! 224: idat[j] ^= ivp[j];
! 225:
! 226: exf->encrypt(sw->sw_kschedule, idat);
! 227: ivp = idat;
! 228: } else { /* decrypt */
! 229: /*
! 230: * Keep encrypted block to be used
! 231: * in next block's processing.
! 232: */
! 233: if (ivp == iv)
! 234: bcopy(idat, piv, blks);
! 235: else
! 236: bcopy(idat, iv, blks);
! 237:
! 238: exf->decrypt(sw->sw_kschedule, idat);
! 239:
! 240: /* XOR with previous block/IV */
! 241: for (j = 0; j < blks; j++)
! 242: idat[j] ^= ivp[j];
! 243:
! 244: if (ivp == iv)
! 245: bcopy(piv, iv, blks);
! 246: else
! 247: ivp = iv;
! 248: }
! 249:
! 250: idat += blks;
! 251: k += blks;
! 252: i -= blks;
! 253: }
! 254: }
! 255: } else {
! 256: /* Find beginning of data */
! 257: count = crd->crd_skip;
! 258: ind = cuio_getptr(uio, count, &k);
! 259: if (ind == -1)
! 260: return EINVAL;
! 261:
! 262: i = crd->crd_len;
! 263:
! 264: while (i > 0) {
! 265: /*
! 266: * If there's insufficient data at the end,
! 267: * we have to do some copying.
! 268: */
! 269: if (uio->uio_iov[ind].iov_len < k + blks &&
! 270: uio->uio_iov[ind].iov_len != k) {
! 271: cuio_copydata(uio, k, blks, blk);
! 272:
! 273: /* Actual encryption/decryption */
! 274: if (exf->reinit) {
! 275: exf->encrypt(sw->sw_kschedule, blk);
! 276: } else if (crd->crd_flags & CRD_F_ENCRYPT) {
! 277: /* XOR with previous block */
! 278: for (j = 0; j < blks; j++)
! 279: blk[j] ^= ivp[j];
! 280:
! 281: exf->encrypt(sw->sw_kschedule, blk);
! 282:
! 283: /*
! 284: * Keep encrypted block for XOR'ing
! 285: * with next block
! 286: */
! 287: bcopy(blk, iv, blks);
! 288: ivp = iv;
! 289: } else { /* decrypt */
! 290: /*
! 291: * Keep encrypted block for XOR'ing
! 292: * with next block
! 293: */
! 294: if (ivp == iv)
! 295: bcopy(blk, piv, blks);
! 296: else
! 297: bcopy(blk, iv, blks);
! 298:
! 299: exf->decrypt(sw->sw_kschedule, blk);
! 300:
! 301: /* XOR with previous block */
! 302: for (j = 0; j < blks; j++)
! 303: blk[j] ^= ivp[j];
! 304:
! 305: if (ivp == iv)
! 306: bcopy(piv, iv, blks);
! 307: else
! 308: ivp = iv;
! 309: }
! 310:
! 311: /* Copy back decrypted block */
! 312: cuio_copyback(uio, k, blks, blk);
! 313:
! 314: count += blks;
! 315:
! 316: /* Advance pointer */
! 317: ind = cuio_getptr(uio, count, &k);
! 318: if (ind == -1)
! 319: return (EINVAL);
! 320:
! 321: i -= blks;
! 322:
! 323: /* Could be done... */
! 324: if (i == 0)
! 325: break;
! 326: }
! 327:
! 328: /*
! 329: * Warning: idat may point to garbage here, but
! 330: * we only use it in the while() loop, only if
! 331: * there are indeed enough data.
! 332: */
! 333: idat = (char *)uio->uio_iov[ind].iov_base + k;
! 334:
! 335: while (uio->uio_iov[ind].iov_len >= k + blks &&
! 336: i > 0) {
! 337: if (exf->reinit) {
! 338: exf->encrypt(sw->sw_kschedule, idat);
! 339: } else if (crd->crd_flags & CRD_F_ENCRYPT) {
! 340: /* XOR with previous block/IV */
! 341: for (j = 0; j < blks; j++)
! 342: idat[j] ^= ivp[j];
! 343:
! 344: exf->encrypt(sw->sw_kschedule, idat);
! 345: ivp = idat;
! 346: } else { /* decrypt */
! 347: /*
! 348: * Keep encrypted block to be used
! 349: * in next block's processing.
! 350: */
! 351: if (ivp == iv)
! 352: bcopy(idat, piv, blks);
! 353: else
! 354: bcopy(idat, iv, blks);
! 355:
! 356: exf->decrypt(sw->sw_kschedule, idat);
! 357:
! 358: /* XOR with previous block/IV */
! 359: for (j = 0; j < blks; j++)
! 360: idat[j] ^= ivp[j];
! 361:
! 362: if (ivp == iv)
! 363: bcopy(piv, iv, blks);
! 364: else
! 365: ivp = iv;
! 366: }
! 367:
! 368: idat += blks;
! 369: count += blks;
! 370: k += blks;
! 371: i -= blks;
! 372: }
! 373: }
! 374: }
! 375:
! 376: return 0; /* Done with encryption/decryption */
! 377: }
! 378:
! 379: /*
! 380: * Compute keyed-hash authenticator.
! 381: */
! 382: int
! 383: swcr_authcompute(struct cryptop *crp, struct cryptodesc *crd,
! 384: struct swcr_data *sw, caddr_t buf, int outtype)
! 385: {
! 386: unsigned char aalg[AALG_MAX_RESULT_LEN];
! 387: struct auth_hash *axf;
! 388: union authctx ctx;
! 389: int err;
! 390:
! 391: if (sw->sw_ictx == 0)
! 392: return EINVAL;
! 393:
! 394: axf = sw->sw_axf;
! 395:
! 396: bcopy(sw->sw_ictx, &ctx, axf->ctxsize);
! 397:
! 398: if (outtype == CRYPTO_BUF_MBUF)
! 399: err = m_apply((struct mbuf *) buf, crd->crd_skip, crd->crd_len,
! 400: (int (*)(caddr_t, caddr_t, unsigned int)) axf->Update,
! 401: (caddr_t) &ctx);
! 402: else
! 403: err = cuio_apply((struct uio *) buf, crd->crd_skip,
! 404: crd->crd_len,
! 405: (int (*)(caddr_t, caddr_t, unsigned int)) axf->Update,
! 406: (caddr_t) &ctx);
! 407:
! 408: if (err)
! 409: return err;
! 410:
! 411: switch (sw->sw_alg) {
! 412: case CRYPTO_MD5_HMAC:
! 413: case CRYPTO_SHA1_HMAC:
! 414: case CRYPTO_RIPEMD160_HMAC:
! 415: case CRYPTO_SHA2_256_HMAC:
! 416: case CRYPTO_SHA2_384_HMAC:
! 417: case CRYPTO_SHA2_512_HMAC:
! 418: if (sw->sw_octx == NULL)
! 419: return EINVAL;
! 420:
! 421: axf->Final(aalg, &ctx);
! 422: bcopy(sw->sw_octx, &ctx, axf->ctxsize);
! 423: axf->Update(&ctx, aalg, axf->hashsize);
! 424: axf->Final(aalg, &ctx);
! 425: break;
! 426:
! 427: case CRYPTO_MD5_KPDK:
! 428: case CRYPTO_SHA1_KPDK:
! 429: if (sw->sw_octx == NULL)
! 430: return EINVAL;
! 431:
! 432: axf->Update(&ctx, sw->sw_octx, sw->sw_klen);
! 433: axf->Final(aalg, &ctx);
! 434: break;
! 435:
! 436: case CRYPTO_MD5:
! 437: case CRYPTO_SHA1:
! 438: axf->Final(aalg, &ctx);
! 439: break;
! 440: }
! 441:
! 442: /* Inject the authentication data */
! 443: if (outtype == CRYPTO_BUF_MBUF)
! 444: COPYBACK(outtype, buf, crd->crd_inject, axf->authsize, aalg);
! 445: else
! 446: bcopy(aalg, crp->crp_mac, axf->authsize);
! 447:
! 448: return 0;
! 449: }
! 450:
! 451: /*
! 452: * Apply a compression/decompression algorithm
! 453: */
! 454: int
! 455: swcr_compdec(struct cryptodesc *crd, struct swcr_data *sw,
! 456: caddr_t buf, int outtype)
! 457: {
! 458: u_int8_t *data, *out;
! 459: struct comp_algo *cxf;
! 460: int adj;
! 461: u_int32_t result;
! 462:
! 463: cxf = sw->sw_cxf;
! 464:
! 465: /* We must handle the whole buffer of data in one time
! 466: * then if there is not all the data in the mbuf, we must
! 467: * copy in a buffer.
! 468: */
! 469:
! 470: MALLOC(data, u_int8_t *, crd->crd_len, M_CRYPTO_DATA, M_NOWAIT);
! 471: if (data == NULL)
! 472: return (EINVAL);
! 473: COPYDATA(outtype, buf, crd->crd_skip, crd->crd_len, data);
! 474:
! 475: if (crd->crd_flags & CRD_F_COMP)
! 476: result = cxf->compress(data, crd->crd_len, &out);
! 477: else
! 478: result = cxf->decompress(data, crd->crd_len, &out);
! 479:
! 480: FREE(data, M_CRYPTO_DATA);
! 481: if (result == 0)
! 482: return EINVAL;
! 483:
! 484: /* Copy back the (de)compressed data. m_copyback is
! 485: * extending the mbuf as necessary.
! 486: */
! 487: sw->sw_size = result;
! 488: /* Check the compressed size when doing compression */
! 489: if (crd->crd_flags & CRD_F_COMP) {
! 490: if (result > crd->crd_len) {
! 491: /* Compression was useless, we lost time */
! 492: FREE(out, M_CRYPTO_DATA);
! 493: return 0;
! 494: }
! 495: }
! 496:
! 497: COPYBACK(outtype, buf, crd->crd_skip, result, out);
! 498: if (result < crd->crd_len) {
! 499: adj = result - crd->crd_len;
! 500: if (outtype == CRYPTO_BUF_MBUF) {
! 501: adj = result - crd->crd_len;
! 502: m_adj((struct mbuf *)buf, adj);
! 503: } else {
! 504: struct uio *uio = (struct uio *)buf;
! 505: int ind;
! 506:
! 507: adj = crd->crd_len - result;
! 508: ind = uio->uio_iovcnt - 1;
! 509:
! 510: while (adj > 0 && ind >= 0) {
! 511: if (adj < uio->uio_iov[ind].iov_len) {
! 512: uio->uio_iov[ind].iov_len -= adj;
! 513: break;
! 514: }
! 515:
! 516: adj -= uio->uio_iov[ind].iov_len;
! 517: uio->uio_iov[ind].iov_len = 0;
! 518: ind--;
! 519: uio->uio_iovcnt--;
! 520: }
! 521: }
! 522: }
! 523: FREE(out, M_CRYPTO_DATA);
! 524: return 0;
! 525: }
! 526:
! 527: /*
! 528: * Generate a new software session.
! 529: */
! 530: int
! 531: swcr_newsession(u_int32_t *sid, struct cryptoini *cri)
! 532: {
! 533: struct swcr_data **swd;
! 534: struct auth_hash *axf;
! 535: struct enc_xform *txf;
! 536: struct comp_algo *cxf;
! 537: u_int32_t i;
! 538: int k;
! 539:
! 540: if (sid == NULL || cri == NULL)
! 541: return EINVAL;
! 542:
! 543: if (swcr_sessions) {
! 544: for (i = 1; i < swcr_sesnum; i++)
! 545: if (swcr_sessions[i] == NULL)
! 546: break;
! 547: }
! 548:
! 549: if (swcr_sessions == NULL || i == swcr_sesnum) {
! 550: if (swcr_sessions == NULL) {
! 551: i = 1; /* We leave swcr_sessions[0] empty */
! 552: swcr_sesnum = CRYPTO_SW_SESSIONS;
! 553: } else
! 554: swcr_sesnum *= 2;
! 555:
! 556: swd = malloc(swcr_sesnum * sizeof(struct swcr_data *),
! 557: M_CRYPTO_DATA, M_NOWAIT);
! 558: if (swd == NULL) {
! 559: /* Reset session number */
! 560: if (swcr_sesnum == CRYPTO_SW_SESSIONS)
! 561: swcr_sesnum = 0;
! 562: else
! 563: swcr_sesnum /= 2;
! 564: return ENOBUFS;
! 565: }
! 566:
! 567: bzero(swd, swcr_sesnum * sizeof(struct swcr_data *));
! 568:
! 569: /* Copy existing sessions */
! 570: if (swcr_sessions) {
! 571: bcopy(swcr_sessions, swd,
! 572: (swcr_sesnum / 2) * sizeof(struct swcr_data *));
! 573: free(swcr_sessions, M_CRYPTO_DATA);
! 574: }
! 575:
! 576: swcr_sessions = swd;
! 577: }
! 578:
! 579: swd = &swcr_sessions[i];
! 580: *sid = i;
! 581:
! 582: while (cri) {
! 583: MALLOC(*swd, struct swcr_data *, sizeof(struct swcr_data),
! 584: M_CRYPTO_DATA, M_NOWAIT);
! 585: if (*swd == NULL) {
! 586: swcr_freesession(i);
! 587: return ENOBUFS;
! 588: }
! 589: bzero(*swd, sizeof(struct swcr_data));
! 590:
! 591: switch (cri->cri_alg) {
! 592: case CRYPTO_DES_CBC:
! 593: txf = &enc_xform_des;
! 594: goto enccommon;
! 595: case CRYPTO_3DES_CBC:
! 596: txf = &enc_xform_3des;
! 597: goto enccommon;
! 598: case CRYPTO_BLF_CBC:
! 599: txf = &enc_xform_blf;
! 600: goto enccommon;
! 601: case CRYPTO_CAST_CBC:
! 602: txf = &enc_xform_cast5;
! 603: goto enccommon;
! 604: case CRYPTO_SKIPJACK_CBC:
! 605: txf = &enc_xform_skipjack;
! 606: goto enccommon;
! 607: case CRYPTO_RIJNDAEL128_CBC:
! 608: txf = &enc_xform_rijndael128;
! 609: goto enccommon;
! 610: case CRYPTO_AES_CTR:
! 611: txf = &enc_xform_aes_ctr;
! 612: goto enccommon;
! 613: case CRYPTO_NULL:
! 614: txf = &enc_xform_null;
! 615: goto enccommon;
! 616: enccommon:
! 617: if (txf->setkey(&((*swd)->sw_kschedule), cri->cri_key,
! 618: cri->cri_klen / 8) < 0) {
! 619: swcr_freesession(i);
! 620: return EINVAL;
! 621: }
! 622: (*swd)->sw_exf = txf;
! 623: break;
! 624:
! 625: case CRYPTO_MD5_HMAC:
! 626: axf = &auth_hash_hmac_md5_96;
! 627: goto authcommon;
! 628: case CRYPTO_SHA1_HMAC:
! 629: axf = &auth_hash_hmac_sha1_96;
! 630: goto authcommon;
! 631: case CRYPTO_RIPEMD160_HMAC:
! 632: axf = &auth_hash_hmac_ripemd_160_96;
! 633: goto authcommon;
! 634: case CRYPTO_SHA2_256_HMAC:
! 635: axf = &auth_hash_hmac_sha2_256_96;
! 636: goto authcommon;
! 637: case CRYPTO_SHA2_384_HMAC:
! 638: axf = &auth_hash_hmac_sha2_384_96;
! 639: goto authcommon;
! 640: case CRYPTO_SHA2_512_HMAC:
! 641: axf = &auth_hash_hmac_sha2_512_96;
! 642: authcommon:
! 643: (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
! 644: M_NOWAIT);
! 645: if ((*swd)->sw_ictx == NULL) {
! 646: swcr_freesession(i);
! 647: return ENOBUFS;
! 648: }
! 649:
! 650: (*swd)->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
! 651: M_NOWAIT);
! 652: if ((*swd)->sw_octx == NULL) {
! 653: swcr_freesession(i);
! 654: return ENOBUFS;
! 655: }
! 656:
! 657: for (k = 0; k < cri->cri_klen / 8; k++)
! 658: cri->cri_key[k] ^= HMAC_IPAD_VAL;
! 659:
! 660: axf->Init((*swd)->sw_ictx);
! 661: axf->Update((*swd)->sw_ictx, cri->cri_key,
! 662: cri->cri_klen / 8);
! 663: axf->Update((*swd)->sw_ictx, hmac_ipad_buffer,
! 664: HMAC_BLOCK_LEN - (cri->cri_klen / 8));
! 665:
! 666: for (k = 0; k < cri->cri_klen / 8; k++)
! 667: cri->cri_key[k] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
! 668:
! 669: axf->Init((*swd)->sw_octx);
! 670: axf->Update((*swd)->sw_octx, cri->cri_key,
! 671: cri->cri_klen / 8);
! 672: axf->Update((*swd)->sw_octx, hmac_opad_buffer,
! 673: HMAC_BLOCK_LEN - (cri->cri_klen / 8));
! 674:
! 675: for (k = 0; k < cri->cri_klen / 8; k++)
! 676: cri->cri_key[k] ^= HMAC_OPAD_VAL;
! 677: (*swd)->sw_axf = axf;
! 678: break;
! 679:
! 680: case CRYPTO_MD5_KPDK:
! 681: axf = &auth_hash_key_md5;
! 682: goto auth2common;
! 683:
! 684: case CRYPTO_SHA1_KPDK:
! 685: axf = &auth_hash_key_sha1;
! 686: auth2common:
! 687: (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
! 688: M_NOWAIT);
! 689: if ((*swd)->sw_ictx == NULL) {
! 690: swcr_freesession(i);
! 691: return ENOBUFS;
! 692: }
! 693:
! 694: /* Store the key so we can "append" it to the payload */
! 695: (*swd)->sw_octx = malloc(cri->cri_klen / 8, M_CRYPTO_DATA,
! 696: M_NOWAIT);
! 697: if ((*swd)->sw_octx == NULL) {
! 698: swcr_freesession(i);
! 699: return ENOBUFS;
! 700: }
! 701:
! 702: (*swd)->sw_klen = cri->cri_klen / 8;
! 703: bcopy(cri->cri_key, (*swd)->sw_octx, cri->cri_klen / 8);
! 704: axf->Init((*swd)->sw_ictx);
! 705: axf->Update((*swd)->sw_ictx, cri->cri_key,
! 706: cri->cri_klen / 8);
! 707: axf->Final(NULL, (*swd)->sw_ictx);
! 708: (*swd)->sw_axf = axf;
! 709: break;
! 710:
! 711: case CRYPTO_MD5:
! 712: axf = &auth_hash_md5;
! 713: goto auth3common;
! 714:
! 715: case CRYPTO_SHA1:
! 716: axf = &auth_hash_sha1;
! 717: auth3common:
! 718: (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
! 719: M_NOWAIT);
! 720: if ((*swd)->sw_ictx == NULL) {
! 721: swcr_freesession(i);
! 722: return ENOBUFS;
! 723: }
! 724:
! 725: axf->Init((*swd)->sw_ictx);
! 726: (*swd)->sw_axf = axf;
! 727: break;
! 728:
! 729: case CRYPTO_DEFLATE_COMP:
! 730: cxf = &comp_algo_deflate;
! 731: (*swd)->sw_cxf = cxf;
! 732: break;
! 733: default:
! 734: swcr_freesession(i);
! 735: return EINVAL;
! 736: }
! 737:
! 738: (*swd)->sw_alg = cri->cri_alg;
! 739: cri = cri->cri_next;
! 740: swd = &((*swd)->sw_next);
! 741: }
! 742: return 0;
! 743: }
! 744:
! 745: /*
! 746: * Free a session.
! 747: */
! 748: int
! 749: swcr_freesession(u_int64_t tid)
! 750: {
! 751: struct swcr_data *swd;
! 752: struct enc_xform *txf;
! 753: struct auth_hash *axf;
! 754: u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
! 755:
! 756: if (sid > swcr_sesnum || swcr_sessions == NULL ||
! 757: swcr_sessions[sid] == NULL)
! 758: return EINVAL;
! 759:
! 760: /* Silently accept and return */
! 761: if (sid == 0)
! 762: return 0;
! 763:
! 764: while ((swd = swcr_sessions[sid]) != NULL) {
! 765: swcr_sessions[sid] = swd->sw_next;
! 766:
! 767: switch (swd->sw_alg) {
! 768: case CRYPTO_DES_CBC:
! 769: case CRYPTO_3DES_CBC:
! 770: case CRYPTO_BLF_CBC:
! 771: case CRYPTO_CAST_CBC:
! 772: case CRYPTO_SKIPJACK_CBC:
! 773: case CRYPTO_RIJNDAEL128_CBC:
! 774: case CRYPTO_AES_CTR:
! 775: case CRYPTO_NULL:
! 776: txf = swd->sw_exf;
! 777:
! 778: if (swd->sw_kschedule)
! 779: txf->zerokey(&(swd->sw_kschedule));
! 780: break;
! 781:
! 782: case CRYPTO_MD5_HMAC:
! 783: case CRYPTO_SHA1_HMAC:
! 784: case CRYPTO_RIPEMD160_HMAC:
! 785: case CRYPTO_SHA2_256_HMAC:
! 786: case CRYPTO_SHA2_384_HMAC:
! 787: case CRYPTO_SHA2_512_HMAC:
! 788: axf = swd->sw_axf;
! 789:
! 790: if (swd->sw_ictx) {
! 791: bzero(swd->sw_ictx, axf->ctxsize);
! 792: free(swd->sw_ictx, M_CRYPTO_DATA);
! 793: }
! 794: if (swd->sw_octx) {
! 795: bzero(swd->sw_octx, axf->ctxsize);
! 796: free(swd->sw_octx, M_CRYPTO_DATA);
! 797: }
! 798: break;
! 799:
! 800: case CRYPTO_MD5_KPDK:
! 801: case CRYPTO_SHA1_KPDK:
! 802: axf = swd->sw_axf;
! 803:
! 804: if (swd->sw_ictx) {
! 805: bzero(swd->sw_ictx, axf->ctxsize);
! 806: free(swd->sw_ictx, M_CRYPTO_DATA);
! 807: }
! 808: if (swd->sw_octx) {
! 809: bzero(swd->sw_octx, swd->sw_klen);
! 810: free(swd->sw_octx, M_CRYPTO_DATA);
! 811: }
! 812: break;
! 813:
! 814: case CRYPTO_MD5:
! 815: case CRYPTO_SHA1:
! 816: axf = swd->sw_axf;
! 817:
! 818: if (swd->sw_ictx)
! 819: free(swd->sw_ictx, M_CRYPTO_DATA);
! 820: break;
! 821: }
! 822:
! 823: FREE(swd, M_CRYPTO_DATA);
! 824: }
! 825: return 0;
! 826: }
! 827:
! 828: /*
! 829: * Process a software request.
! 830: */
! 831: int
! 832: swcr_process(struct cryptop *crp)
! 833: {
! 834: struct cryptodesc *crd;
! 835: struct swcr_data *sw;
! 836: u_int32_t lid;
! 837: int type;
! 838:
! 839: /* Sanity check */
! 840: if (crp == NULL)
! 841: return EINVAL;
! 842:
! 843: if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
! 844: crp->crp_etype = EINVAL;
! 845: goto done;
! 846: }
! 847:
! 848: lid = crp->crp_sid & 0xffffffff;
! 849: if (lid >= swcr_sesnum || lid == 0 || swcr_sessions[lid] == NULL) {
! 850: crp->crp_etype = ENOENT;
! 851: goto done;
! 852: }
! 853:
! 854: if (crp->crp_flags & CRYPTO_F_IMBUF)
! 855: type = CRYPTO_BUF_MBUF;
! 856: else
! 857: type = CRYPTO_BUF_IOV;
! 858:
! 859: /* Go through crypto descriptors, processing as we go */
! 860: for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
! 861: /*
! 862: * Find the crypto context.
! 863: *
! 864: * XXX Note that the logic here prevents us from having
! 865: * XXX the same algorithm multiple times in a session
! 866: * XXX (or rather, we can but it won't give us the right
! 867: * XXX results). To do that, we'd need some way of differentiating
! 868: * XXX between the various instances of an algorithm (so we can
! 869: * XXX locate the correct crypto context).
! 870: */
! 871: for (sw = swcr_sessions[lid];
! 872: sw && sw->sw_alg != crd->crd_alg;
! 873: sw = sw->sw_next)
! 874: ;
! 875:
! 876: /* No such context ? */
! 877: if (sw == NULL) {
! 878: crp->crp_etype = EINVAL;
! 879: goto done;
! 880: }
! 881:
! 882: switch (sw->sw_alg) {
! 883: case CRYPTO_NULL:
! 884: break;
! 885: case CRYPTO_DES_CBC:
! 886: case CRYPTO_3DES_CBC:
! 887: case CRYPTO_BLF_CBC:
! 888: case CRYPTO_CAST_CBC:
! 889: case CRYPTO_SKIPJACK_CBC:
! 890: case CRYPTO_RIJNDAEL128_CBC:
! 891: case CRYPTO_AES_CTR:
! 892: if ((crp->crp_etype = swcr_encdec(crd, sw,
! 893: crp->crp_buf, type)) != 0)
! 894: goto done;
! 895: break;
! 896: case CRYPTO_MD5_HMAC:
! 897: case CRYPTO_SHA1_HMAC:
! 898: case CRYPTO_RIPEMD160_HMAC:
! 899: case CRYPTO_SHA2_256_HMAC:
! 900: case CRYPTO_SHA2_384_HMAC:
! 901: case CRYPTO_SHA2_512_HMAC:
! 902: case CRYPTO_MD5_KPDK:
! 903: case CRYPTO_SHA1_KPDK:
! 904: case CRYPTO_MD5:
! 905: case CRYPTO_SHA1:
! 906: if ((crp->crp_etype = swcr_authcompute(crp, crd, sw,
! 907: crp->crp_buf, type)) != 0)
! 908: goto done;
! 909: break;
! 910:
! 911: case CRYPTO_DEFLATE_COMP:
! 912: if ((crp->crp_etype = swcr_compdec(crd, sw,
! 913: crp->crp_buf, type)) != 0)
! 914: goto done;
! 915: else
! 916: crp->crp_olen = (int)sw->sw_size;
! 917: break;
! 918:
! 919: default:
! 920: /* Unknown/unsupported algorithm */
! 921: crp->crp_etype = EINVAL;
! 922: goto done;
! 923: }
! 924: }
! 925:
! 926: done:
! 927: crypto_done(crp);
! 928: return 0;
! 929: }
! 930:
! 931: /*
! 932: * Initialize the driver, called from the kernel main().
! 933: */
! 934: void
! 935: swcr_init(void)
! 936: {
! 937: int algs[CRYPTO_ALGORITHM_MAX + 1];
! 938: int flags = CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_ENCRYPT_MAC |
! 939: CRYPTOCAP_F_MAC_ENCRYPT;
! 940:
! 941: swcr_id = crypto_get_driverid(flags);
! 942: if (swcr_id < 0) {
! 943: /* This should never happen */
! 944: panic("Software crypto device cannot initialize!");
! 945: }
! 946:
! 947: bzero(algs, sizeof(algs));
! 948:
! 949: algs[CRYPTO_DES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 950: algs[CRYPTO_3DES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 951: algs[CRYPTO_BLF_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 952: algs[CRYPTO_CAST_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 953: algs[CRYPTO_SKIPJACK_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 954: algs[CRYPTO_MD5_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 955: algs[CRYPTO_SHA1_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 956: algs[CRYPTO_RIPEMD160_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 957: algs[CRYPTO_MD5_KPDK] = CRYPTO_ALG_FLAG_SUPPORTED;
! 958: algs[CRYPTO_SHA1_KPDK] = CRYPTO_ALG_FLAG_SUPPORTED;
! 959: algs[CRYPTO_MD5] = CRYPTO_ALG_FLAG_SUPPORTED;
! 960: algs[CRYPTO_SHA1] = CRYPTO_ALG_FLAG_SUPPORTED;
! 961: algs[CRYPTO_RIJNDAEL128_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 962: algs[CRYPTO_AES_CTR] = CRYPTO_ALG_FLAG_SUPPORTED;
! 963: algs[CRYPTO_DEFLATE_COMP] = CRYPTO_ALG_FLAG_SUPPORTED;
! 964: algs[CRYPTO_NULL] = CRYPTO_ALG_FLAG_SUPPORTED;
! 965: algs[CRYPTO_SHA2_256_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 966: algs[CRYPTO_SHA2_384_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 967: algs[CRYPTO_SHA2_512_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
! 968:
! 969: crypto_register(swcr_id, algs, swcr_newsession,
! 970: swcr_freesession, swcr_process);
! 971: }
CVSweb