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