1 /* $NetBSD: cgd_crypto.c,v 1.15 2017/01/02 14:28:29 alnsn Exp $ */ 2 3 /*- 4 * Copyright (c) 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Roland C. Dowdeswell. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Crypto Framework For cgd.c 34 * 35 * This framework is temporary and awaits a more complete 36 * kernel wide crypto implementation. 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: cgd_crypto.c,v 1.15 2017/01/02 14:28:29 alnsn Exp $"); 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/malloc.h> 45 46 #include <dev/cgd_crypto.h> 47 48 #include <crypto/rijndael/rijndael-api-fst.h> 49 #include <crypto/des/des.h> 50 #include <crypto/blowfish/blowfish.h> 51 52 #ifdef DIAGNOSTIC 53 #define DIAGPANIC(x) panic x 54 #else 55 #define DIAGPANIC(x) 56 #endif 57 58 /* 59 * The general framework provides only one generic function. 60 * It takes the name of an algorith and returns a struct cryptfuncs * 61 * for it. It is up to the initialisation routines of the algorithm 62 * to check key size and block size. 63 */ 64 65 static cfunc_init cgd_cipher_aes_cbc_init; 66 static cfunc_destroy cgd_cipher_aes_cbc_destroy; 67 static cfunc_cipher cgd_cipher_aes_cbc; 68 static cfunc_cipher_prep cgd_cipher_aes_cbc_prep; 69 70 static cfunc_init cgd_cipher_aes_xts_init; 71 static cfunc_destroy cgd_cipher_aes_xts_destroy; 72 static cfunc_cipher cgd_cipher_aes_xts; 73 static cfunc_cipher_prep cgd_cipher_aes_xts_prep; 74 75 static cfunc_init cgd_cipher_3des_init; 76 static cfunc_destroy cgd_cipher_3des_destroy; 77 static cfunc_cipher cgd_cipher_3des_cbc; 78 static cfunc_cipher_prep cgd_cipher_3des_cbc_prep; 79 80 static cfunc_init cgd_cipher_bf_init; 81 static cfunc_destroy cgd_cipher_bf_destroy; 82 static cfunc_cipher cgd_cipher_bf_cbc; 83 static cfunc_cipher_prep cgd_cipher_bf_cbc_prep; 84 85 static const struct cryptfuncs cf[] = { 86 { 87 .cf_name = "aes-xts", 88 .cf_init = cgd_cipher_aes_xts_init, 89 .cf_destroy = cgd_cipher_aes_xts_destroy, 90 .cf_cipher = cgd_cipher_aes_xts, 91 .cf_cipher_prep = cgd_cipher_aes_xts_prep, 92 }, 93 { 94 .cf_name = "aes-cbc", 95 .cf_init = cgd_cipher_aes_cbc_init, 96 .cf_destroy = cgd_cipher_aes_cbc_destroy, 97 .cf_cipher = cgd_cipher_aes_cbc, 98 .cf_cipher_prep = cgd_cipher_aes_cbc_prep, 99 }, 100 { 101 .cf_name = "3des-cbc", 102 .cf_init = cgd_cipher_3des_init, 103 .cf_destroy = cgd_cipher_3des_destroy, 104 .cf_cipher = cgd_cipher_3des_cbc, 105 .cf_cipher_prep = cgd_cipher_3des_cbc_prep, 106 }, 107 { 108 .cf_name = "blowfish-cbc", 109 .cf_init = cgd_cipher_bf_init, 110 .cf_destroy = cgd_cipher_bf_destroy, 111 .cf_cipher = cgd_cipher_bf_cbc, 112 .cf_cipher_prep = cgd_cipher_bf_cbc_prep, 113 }, 114 }; 115 const struct cryptfuncs * 116 cryptfuncs_find(const char *alg) 117 { 118 119 for (size_t i = 0; i < __arraycount(cf); i++) 120 if (strcmp(cf[i].cf_name, alg) == 0) 121 return &cf[i]; 122 123 return NULL; 124 } 125 126 typedef void (*cipher_func)(void *, void *, const void *, size_t); 127 128 static void 129 cgd_cipher_uio(void *privdata, cipher_func cipher, 130 struct uio *dstuio, struct uio *srcuio); 131 132 /* 133 * cgd_cipher_uio takes a simple cbc or xts cipher and iterates 134 * it over two struct uio's. It presumes that the cipher function 135 * that is passed to it keeps the IV state between calls. 136 * 137 * We assume that the caller has ensured that each segment is evenly 138 * divisible by the block size, which for the cgd is a valid assumption. 139 * If we were to make this code more generic, we might need to take care 140 * of this case, either by issuing an error or copying the data. 141 */ 142 143 static void 144 cgd_cipher_uio(void *privdata, cipher_func cipher, 145 struct uio *dstuio, struct uio *srcuio) 146 { 147 const struct iovec *dst; 148 const struct iovec *src; 149 int dstnum; 150 int dstoff = 0; 151 int srcnum; 152 int srcoff = 0; 153 154 dst = dstuio->uio_iov; 155 dstnum = dstuio->uio_iovcnt; 156 src = srcuio->uio_iov; 157 srcnum = srcuio->uio_iovcnt; 158 for (;;) { 159 int l = MIN(dst->iov_len - dstoff, src->iov_len - srcoff); 160 u_int8_t *d = (u_int8_t *)dst->iov_base + dstoff; 161 const u_int8_t *s = (const u_int8_t *)src->iov_base + srcoff; 162 163 cipher(privdata, d, s, l); 164 165 dstoff += l; 166 srcoff += l; 167 /* 168 * We assume that {dst,src} == {dst,src}->iov_len, 169 * because it should not be possible for it not to be. 170 */ 171 if (dstoff == dst->iov_len) { 172 dstoff = 0; 173 dstnum--; 174 dst++; 175 } 176 if (srcoff == src->iov_len) { 177 srcoff = 0; 178 srcnum--; 179 src++; 180 } 181 if (!srcnum || !dstnum) 182 break; 183 } 184 } 185 186 /* 187 * AES Framework 188 */ 189 190 /* 191 * NOTE: we do not store the blocksize in here, because it is not 192 * variable [yet], we hardcode the blocksize to 16 (128 bits). 193 */ 194 195 struct aes_privdata { 196 keyInstance ap_enckey; 197 keyInstance ap_deckey; 198 }; 199 200 struct aes_encdata { 201 keyInstance *ae_key; /* key for this direction */ 202 u_int8_t ae_iv[CGD_AES_BLOCK_SIZE]; /* Initialization Vector */ 203 }; 204 205 static void * 206 cgd_cipher_aes_cbc_init(size_t keylen, const void *key, size_t *blocksize) 207 { 208 struct aes_privdata *ap; 209 210 if (!blocksize) 211 return NULL; 212 if (keylen != 128 && keylen != 192 && keylen != 256) 213 return NULL; 214 if (*blocksize == (size_t)-1) 215 *blocksize = 128; 216 if (*blocksize != 128) 217 return NULL; 218 ap = malloc(sizeof(*ap), M_DEVBUF, 0); 219 if (!ap) 220 return NULL; 221 rijndael_makeKey(&ap->ap_enckey, DIR_ENCRYPT, keylen, key); 222 rijndael_makeKey(&ap->ap_deckey, DIR_DECRYPT, keylen, key); 223 return ap; 224 } 225 226 static void 227 cgd_cipher_aes_cbc_destroy(void *data) 228 { 229 struct aes_privdata *apd = data; 230 231 explicit_memset(apd, 0, sizeof(*apd)); 232 free(apd, M_DEVBUF); 233 } 234 235 static void 236 cgd_cipher_aes_cbc_prep(void *privdata, char *iv, 237 const char *blkno_buf, size_t blocksize, int dir) 238 { 239 struct aes_privdata *apd = privdata; 240 cipherInstance cipher; 241 int cipher_ok __diagused; 242 243 cipher_ok = rijndael_cipherInit(&cipher, MODE_CBC, NULL); 244 KASSERT(cipher_ok > 0); 245 rijndael_blockEncrypt(&cipher, &apd->ap_enckey, 246 blkno_buf, blocksize * 8, iv); 247 if (blocksize > CGD_AES_BLOCK_SIZE) { 248 (void)memmove(iv, iv + blocksize - CGD_AES_BLOCK_SIZE, 249 CGD_AES_BLOCK_SIZE); 250 } 251 } 252 253 static void 254 aes_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len) 255 { 256 struct aes_encdata *ae = privdata; 257 cipherInstance cipher; 258 int cipher_ok __diagused; 259 260 cipher_ok = rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv); 261 KASSERT(cipher_ok > 0); 262 rijndael_blockEncrypt(&cipher, ae->ae_key, src, len * 8, dst); 263 (void)memcpy(ae->ae_iv, (u_int8_t *)dst + 264 (len - CGD_AES_BLOCK_SIZE), CGD_AES_BLOCK_SIZE); 265 } 266 267 static void 268 aes_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len) 269 { 270 struct aes_encdata *ae = privdata; 271 cipherInstance cipher; 272 int cipher_ok __diagused; 273 274 cipher_ok = rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv); 275 KASSERT(cipher_ok > 0); 276 rijndael_blockDecrypt(&cipher, ae->ae_key, src, len * 8, dst); 277 (void)memcpy(ae->ae_iv, (const u_int8_t *)src + 278 (len - CGD_AES_BLOCK_SIZE), CGD_AES_BLOCK_SIZE); 279 } 280 281 static void 282 cgd_cipher_aes_cbc(void *privdata, struct uio *dstuio, 283 struct uio *srcuio, const void *iv, int dir) 284 { 285 struct aes_privdata *apd = privdata; 286 struct aes_encdata encd; 287 288 (void)memcpy(encd.ae_iv, iv, CGD_AES_BLOCK_SIZE); 289 switch (dir) { 290 case CGD_CIPHER_ENCRYPT: 291 encd.ae_key = &apd->ap_enckey; 292 cgd_cipher_uio(&encd, aes_cbc_enc_int, dstuio, srcuio); 293 break; 294 case CGD_CIPHER_DECRYPT: 295 encd.ae_key = &apd->ap_deckey; 296 cgd_cipher_uio(&encd, aes_cbc_dec_int, dstuio, srcuio); 297 break; 298 default: 299 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir)); 300 } 301 } 302 303 static void * 304 cgd_cipher_aes_xts_init(size_t keylen, const void *xtskey, size_t *blocksize) 305 { 306 struct aes_privdata *ap; 307 const char *key, *key2; /* XTS key is made of two AES keys. */ 308 309 if (!blocksize) 310 return NULL; 311 if (keylen != 256 && keylen != 512) 312 return NULL; 313 if (*blocksize == (size_t)-1) 314 *blocksize = 128; 315 if (*blocksize != 128) 316 return NULL; 317 ap = malloc(2 * sizeof(*ap), M_DEVBUF, 0); 318 if (!ap) 319 return NULL; 320 321 keylen /= 2; 322 key = xtskey; 323 key2 = key + keylen / CHAR_BIT; 324 325 rijndael_makeKey(&ap[0].ap_enckey, DIR_ENCRYPT, keylen, key); 326 rijndael_makeKey(&ap[0].ap_deckey, DIR_DECRYPT, keylen, key); 327 rijndael_makeKey(&ap[1].ap_enckey, DIR_ENCRYPT, keylen, key2); 328 329 return ap; 330 } 331 332 static void 333 cgd_cipher_aes_xts_destroy(void *data) 334 { 335 struct aes_privdata *apd = data; 336 337 explicit_memset(apd, 0, 2 * sizeof(*apd)); 338 free(apd, M_DEVBUF); 339 } 340 341 static void 342 cgd_cipher_aes_xts_prep(void *privdata, char *iv, 343 const char *blkno_buf, size_t blocksize, int dir) 344 { 345 struct aes_privdata *apd = privdata; 346 cipherInstance cipher; 347 int cipher_ok __diagused; 348 349 cipher_ok = rijndael_cipherInit(&cipher, MODE_ECB, NULL); 350 KASSERT(cipher_ok > 0); 351 rijndael_blockEncrypt(&cipher, &apd[1].ap_enckey, 352 blkno_buf, blocksize * 8, iv); 353 } 354 355 static void 356 aes_xts_enc_int(void *privdata, void *dst, const void *src, size_t len) 357 { 358 struct aes_encdata *ae = privdata; 359 cipherInstance cipher; 360 int cipher_ok __diagused; 361 362 cipher_ok = rijndael_cipherInit(&cipher, MODE_XTS, ae->ae_iv); 363 KASSERT(cipher_ok > 0); 364 rijndael_blockEncrypt(&cipher, ae->ae_key, src, len * 8, dst); 365 (void)memcpy(ae->ae_iv, cipher.IV, CGD_AES_BLOCK_SIZE); 366 } 367 368 static void 369 aes_xts_dec_int(void *privdata, void *dst, const void *src, size_t len) 370 { 371 struct aes_encdata *ae = privdata; 372 cipherInstance cipher; 373 int cipher_ok __diagused; 374 375 cipher_ok = rijndael_cipherInit(&cipher, MODE_XTS, ae->ae_iv); 376 KASSERT(cipher_ok > 0); 377 rijndael_blockDecrypt(&cipher, ae->ae_key, src, len * 8, dst); 378 (void)memcpy(ae->ae_iv, cipher.IV, CGD_AES_BLOCK_SIZE); 379 } 380 381 static void 382 cgd_cipher_aes_xts(void *privdata, struct uio *dstuio, 383 struct uio *srcuio, const void *iv, int dir) 384 { 385 struct aes_privdata *apd = privdata; 386 struct aes_encdata encd; 387 388 (void)memcpy(encd.ae_iv, iv, CGD_AES_BLOCK_SIZE); 389 switch (dir) { 390 case CGD_CIPHER_ENCRYPT: 391 encd.ae_key = &apd->ap_enckey; 392 cgd_cipher_uio(&encd, aes_xts_enc_int, dstuio, srcuio); 393 break; 394 case CGD_CIPHER_DECRYPT: 395 encd.ae_key = &apd->ap_deckey; 396 cgd_cipher_uio(&encd, aes_xts_dec_int, dstuio, srcuio); 397 break; 398 default: 399 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir)); 400 } 401 } 402 403 /* 404 * 3DES Framework 405 */ 406 407 struct c3des_privdata { 408 des_key_schedule cp_key1; 409 des_key_schedule cp_key2; 410 des_key_schedule cp_key3; 411 }; 412 413 struct c3des_encdata { 414 des_key_schedule *ce_key1; 415 des_key_schedule *ce_key2; 416 des_key_schedule *ce_key3; 417 u_int8_t ce_iv[CGD_3DES_BLOCK_SIZE]; 418 }; 419 420 static void * 421 cgd_cipher_3des_init(size_t keylen, const void *key, size_t *blocksize) 422 { 423 struct c3des_privdata *cp; 424 int error = 0; 425 des_cblock *block; 426 427 if (!blocksize) 428 return NULL; 429 if (*blocksize == (size_t)-1) 430 *blocksize = 64; 431 if (keylen != (DES_KEY_SZ * 3 * 8) || *blocksize != 64) 432 return NULL; 433 cp = malloc(sizeof(*cp), M_DEVBUF, 0); 434 if (!cp) 435 return NULL; 436 block = __UNCONST(key); 437 error = des_key_sched(block, cp->cp_key1); 438 error |= des_key_sched(block + 1, cp->cp_key2); 439 error |= des_key_sched(block + 2, cp->cp_key3); 440 if (error) { 441 explicit_memset(cp, 0, sizeof(*cp)); 442 free(cp, M_DEVBUF); 443 return NULL; 444 } 445 return cp; 446 } 447 448 static void 449 cgd_cipher_3des_destroy(void *data) 450 { 451 struct c3des_privdata *cp = data; 452 453 explicit_memset(cp, 0, sizeof(*cp)); 454 free(cp, M_DEVBUF); 455 } 456 457 static void 458 cgd_cipher_3des_cbc_prep(void *privdata, char *iv, 459 const char *blkno_buf, size_t blocksize, int dir) 460 { 461 struct c3des_privdata *cp = privdata; 462 char zero_iv[CGD_3DES_BLOCK_SIZE]; 463 464 memset(zero_iv, 0, sizeof(zero_iv)); 465 des_ede3_cbc_encrypt(blkno_buf, iv, blocksize, 466 cp->cp_key1, cp->cp_key2, cp->cp_key3, (des_cblock *)zero_iv, 1); 467 if (blocksize > CGD_3DES_BLOCK_SIZE) { 468 (void)memmove(iv, iv + blocksize - CGD_3DES_BLOCK_SIZE, 469 CGD_3DES_BLOCK_SIZE); 470 } 471 } 472 473 static void 474 c3des_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len) 475 { 476 struct c3des_encdata *ce = privdata; 477 478 des_ede3_cbc_encrypt(src, dst, len, *ce->ce_key1, *ce->ce_key2, 479 *ce->ce_key3, (des_cblock *)ce->ce_iv, 1); 480 (void)memcpy(ce->ce_iv, (const u_int8_t *)dst + 481 (len - CGD_3DES_BLOCK_SIZE), CGD_3DES_BLOCK_SIZE); 482 } 483 484 static void 485 c3des_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len) 486 { 487 struct c3des_encdata *ce = privdata; 488 489 des_ede3_cbc_encrypt(src, dst, len, *ce->ce_key1, *ce->ce_key2, 490 *ce->ce_key3, (des_cblock *)ce->ce_iv, 0); 491 (void)memcpy(ce->ce_iv, (const u_int8_t *)src + 492 (len - CGD_3DES_BLOCK_SIZE), CGD_3DES_BLOCK_SIZE); 493 } 494 495 static void 496 cgd_cipher_3des_cbc(void *privdata, struct uio *dstuio, 497 struct uio *srcuio, const void *iv, int dir) 498 { 499 struct c3des_privdata *cp = privdata; 500 struct c3des_encdata ce; 501 502 (void)memcpy(ce.ce_iv, iv, CGD_3DES_BLOCK_SIZE); 503 ce.ce_key1 = &cp->cp_key1; 504 ce.ce_key2 = &cp->cp_key2; 505 ce.ce_key3 = &cp->cp_key3; 506 switch (dir) { 507 case CGD_CIPHER_ENCRYPT: 508 cgd_cipher_uio(&ce, c3des_cbc_enc_int, dstuio, srcuio); 509 break; 510 case CGD_CIPHER_DECRYPT: 511 cgd_cipher_uio(&ce, c3des_cbc_dec_int, dstuio, srcuio); 512 break; 513 default: 514 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir)); 515 } 516 } 517 518 /* 519 * Blowfish Framework 520 */ 521 522 struct bf_privdata { 523 BF_KEY bp_key; 524 }; 525 526 struct bf_encdata { 527 BF_KEY *be_key; 528 u_int8_t be_iv[CGD_BF_BLOCK_SIZE]; 529 }; 530 531 static void * 532 cgd_cipher_bf_init(size_t keylen, const void *key, size_t *blocksize) 533 { 534 struct bf_privdata *bp; 535 536 if (!blocksize) 537 return NULL; 538 if (keylen < 40 || keylen > 448 || (keylen % 8 != 0)) 539 return NULL; 540 if (*blocksize == (size_t)-1) 541 *blocksize = 64; 542 if (*blocksize != 64) 543 return NULL; 544 bp = malloc(sizeof(*bp), M_DEVBUF, 0); 545 if (!bp) 546 return NULL; 547 BF_set_key(&bp->bp_key, keylen / 8, key); 548 return bp; 549 } 550 551 static void 552 cgd_cipher_bf_destroy(void *data) 553 { 554 struct bf_privdata *bp = data; 555 556 explicit_memset(bp, 0, sizeof(*bp)); 557 free(bp, M_DEVBUF); 558 } 559 560 static void 561 cgd_cipher_bf_cbc_prep(void *privdata, char *iv, 562 const char *blkno_buf, size_t blocksize, int dir) 563 { 564 struct bf_privdata *bp = privdata; 565 char zero_iv[CGD_BF_BLOCK_SIZE]; 566 567 memset(zero_iv, 0, sizeof(zero_iv)); 568 BF_cbc_encrypt(blkno_buf, iv, blocksize, &bp->bp_key, zero_iv, 1); 569 if (blocksize > CGD_BF_BLOCK_SIZE) { 570 (void)memmove(iv, iv + blocksize - CGD_BF_BLOCK_SIZE, 571 CGD_BF_BLOCK_SIZE); 572 } 573 } 574 575 static void 576 bf_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len) 577 { 578 struct bf_encdata *be = privdata; 579 580 BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 1); 581 (void)memcpy(be->be_iv, (u_int8_t *)dst + 582 (len - CGD_BF_BLOCK_SIZE), CGD_BF_BLOCK_SIZE); 583 } 584 585 static void 586 bf_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len) 587 { 588 struct bf_encdata *be = privdata; 589 590 BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 0); 591 (void)memcpy(be->be_iv, (const u_int8_t *)src + 592 (len - CGD_BF_BLOCK_SIZE), CGD_BF_BLOCK_SIZE); 593 } 594 595 static void 596 cgd_cipher_bf_cbc(void *privdata, struct uio *dstuio, 597 struct uio *srcuio, const void *iv, int dir) 598 { 599 struct bf_privdata *bp = privdata; 600 struct bf_encdata be; 601 602 (void)memcpy(be.be_iv, iv, CGD_BF_BLOCK_SIZE); 603 be.be_key = &bp->bp_key; 604 switch (dir) { 605 case CGD_CIPHER_ENCRYPT: 606 cgd_cipher_uio(&be, bf_cbc_enc_int, dstuio, srcuio); 607 break; 608 case CGD_CIPHER_DECRYPT: 609 cgd_cipher_uio(&be, bf_cbc_dec_int, dstuio, srcuio); 610 break; 611 default: 612 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir)); 613 } 614 615 } 616