apr_crypto_nss.c revision 362181
1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "apr_lib.h" 18#include "apu.h" 19#include "apu_config.h" 20#include "apu_errno.h" 21 22#include <ctype.h> 23#include <stdlib.h> 24 25#include "apr_strings.h" 26#include "apr_time.h" 27#include "apr_buckets.h" 28 29#include "apr_crypto_internal.h" 30 31#if APU_HAVE_CRYPTO 32 33#include <prerror.h> 34 35#ifdef HAVE_NSS_NSS_H 36#include <nss/nss.h> 37#endif 38#ifdef HAVE_NSS_H 39#include <nss.h> 40#endif 41 42#ifdef HAVE_NSS_PK11PUB_H 43#include <nss/pk11pub.h> 44#endif 45#ifdef HAVE_PK11PUB_H 46#include <pk11pub.h> 47#endif 48 49struct apr_crypto_t { 50 apr_pool_t *pool; 51 const apr_crypto_driver_t *provider; 52 apu_err_t *result; 53 apr_crypto_config_t *config; 54 apr_hash_t *types; 55 apr_hash_t *modes; 56}; 57 58struct apr_crypto_config_t { 59 void *opaque; 60}; 61 62struct apr_crypto_key_t { 63 apr_pool_t *pool; 64 const apr_crypto_driver_t *provider; 65 const apr_crypto_t *f; 66 CK_MECHANISM_TYPE cipherMech; 67 SECOidTag cipherOid; 68 PK11SymKey *symKey; 69 int ivSize; 70 int keyLength; 71}; 72 73struct apr_crypto_block_t { 74 apr_pool_t *pool; 75 const apr_crypto_driver_t *provider; 76 const apr_crypto_t *f; 77 PK11Context *ctx; 78 apr_crypto_key_t *key; 79 SECItem *secParam; 80 int blockSize; 81}; 82 83static struct apr_crypto_block_key_type_t key_types[] = 84{ 85{ APR_KEY_3DES_192, 24, 8, 8 }, 86{ APR_KEY_AES_128, 16, 16, 16 }, 87{ APR_KEY_AES_192, 24, 16, 16 }, 88{ APR_KEY_AES_256, 32, 16, 16 } }; 89 90static struct apr_crypto_block_key_mode_t key_modes[] = 91{ 92{ APR_MODE_ECB }, 93{ APR_MODE_CBC } }; 94 95/* sufficient space to wrap a key */ 96#define BUFFER_SIZE 128 97 98/** 99 * Fetch the most recent error from this driver. 100 */ 101static apr_status_t crypto_error(const apu_err_t **result, 102 const apr_crypto_t *f) 103{ 104 *result = f->result; 105 return APR_SUCCESS; 106} 107 108/** 109 * Shutdown the crypto library and release resources. 110 * 111 * It is safe to shut down twice. 112 */ 113static apr_status_t crypto_shutdown(void) 114{ 115 if (NSS_IsInitialized()) { 116 SECStatus s = NSS_Shutdown(); 117 if (s != SECSuccess) { 118 fprintf(stderr, "NSS failed to shutdown, possible leak: %d: %s", 119 PR_GetError(), PR_ErrorToName(s)); 120 return APR_EINIT; 121 } 122 } 123 return APR_SUCCESS; 124} 125 126static apr_status_t crypto_shutdown_helper(void *data) 127{ 128 return crypto_shutdown(); 129} 130 131/** 132 * Initialise the crypto library and perform one time initialisation. 133 */ 134static apr_status_t crypto_init(apr_pool_t *pool, const char *params, 135 const apu_err_t **result) 136{ 137 SECStatus s; 138 const char *dir = NULL; 139 const char *keyPrefix = NULL; 140 const char *certPrefix = NULL; 141 const char *secmod = NULL; 142 int noinit = 0; 143 PRUint32 flags = 0; 144 145 struct { 146 const char *field; 147 const char *value; 148 int set; 149 } fields[] = { 150 { "dir", NULL, 0 }, 151 { "key3", NULL, 0 }, 152 { "cert7", NULL, 0 }, 153 { "secmod", NULL, 0 }, 154 { "noinit", NULL, 0 }, 155 { NULL, NULL, 0 } 156 }; 157 const char *ptr; 158 size_t klen; 159 char **elts = NULL; 160 char *elt; 161 int i = 0, j; 162 apr_status_t status; 163 164 if (params) { 165 if (APR_SUCCESS != (status = apr_tokenize_to_argv(params, &elts, pool))) { 166 return status; 167 } 168 while ((elt = elts[i])) { 169 ptr = strchr(elt, '='); 170 if (ptr) { 171 for (klen = ptr - elt; klen && apr_isspace(elt[klen - 1]); --klen) 172 ; 173 ptr++; 174 } 175 else { 176 for (klen = strlen(elt); klen && apr_isspace(elt[klen - 1]); --klen) 177 ; 178 } 179 elt[klen] = 0; 180 181 for (j = 0; fields[j].field != NULL; ++j) { 182 if (klen && !strcasecmp(fields[j].field, elt)) { 183 fields[j].set = 1; 184 if (ptr) { 185 fields[j].value = ptr; 186 } 187 break; 188 } 189 } 190 191 i++; 192 } 193 dir = fields[0].value; 194 keyPrefix = fields[1].value; 195 certPrefix = fields[2].value; 196 secmod = fields[3].value; 197 noinit = fields[4].set; 198 } 199 200 /* if we've been asked to bypass, do so here */ 201 if (noinit) { 202 return APR_SUCCESS; 203 } 204 205 /* sanity check - we can only initialise NSS once */ 206 if (NSS_IsInitialized()) { 207 return APR_EREINIT; 208 } 209 210 if (keyPrefix || certPrefix || secmod) { 211 s = NSS_Initialize(dir, certPrefix, keyPrefix, secmod, flags); 212 } 213 else if (dir) { 214 s = NSS_InitReadWrite(dir); 215 } 216 else { 217 s = NSS_NoDB_Init(NULL); 218 } 219 if (s != SECSuccess) { 220 if (result) { 221 /* Note: all memory must be owned by the caller, in case we're unloaded */ 222 apu_err_t *err = apr_pcalloc(pool, sizeof(apu_err_t)); 223 err->rc = PR_GetError(); 224 err->msg = apr_pstrdup(pool, PR_ErrorToName(s)); 225 err->reason = apr_pstrdup(pool, "Error during 'nss' initialisation"); 226 *result = err; 227 } 228 229 return APR_ECRYPT; 230 } 231 232 apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper, 233 apr_pool_cleanup_null); 234 235 return APR_SUCCESS; 236 237} 238 239/** 240 * @brief Clean encryption / decryption context. 241 * @note After cleanup, a context is free to be reused if necessary. 242 * @param f The context to use. 243 * @return Returns APR_ENOTIMPL if not supported. 244 */ 245static apr_status_t crypto_block_cleanup(apr_crypto_block_t *block) 246{ 247 248 if (block->secParam) { 249 SECITEM_FreeItem(block->secParam, PR_TRUE); 250 block->secParam = NULL; 251 } 252 253 if (block->ctx) { 254 PK11_DestroyContext(block->ctx, PR_TRUE); 255 block->ctx = NULL; 256 } 257 258 return APR_SUCCESS; 259 260} 261 262static apr_status_t crypto_block_cleanup_helper(void *data) 263{ 264 apr_crypto_block_t *block = (apr_crypto_block_t *) data; 265 return crypto_block_cleanup(block); 266} 267 268static apr_status_t crypto_key_cleanup(void *data) 269{ 270 apr_crypto_key_t *key = data; 271 if (key->symKey) { 272 PK11_FreeSymKey(key->symKey); 273 key->symKey = NULL; 274 } 275 return APR_SUCCESS; 276} 277/** 278 * @brief Clean encryption / decryption context. 279 * @note After cleanup, a context is free to be reused if necessary. 280 * @param f The context to use. 281 * @return Returns APR_ENOTIMPL if not supported. 282 */ 283static apr_status_t crypto_cleanup(apr_crypto_t *f) 284{ 285 return APR_SUCCESS; 286} 287 288static apr_status_t crypto_cleanup_helper(void *data) 289{ 290 apr_crypto_t *f = (apr_crypto_t *) data; 291 return crypto_cleanup(f); 292} 293 294/** 295 * @brief Create a context for supporting encryption. Keys, certificates, 296 * algorithms and other parameters will be set per context. More than 297 * one context can be created at one time. A cleanup will be automatically 298 * registered with the given pool to guarantee a graceful shutdown. 299 * @param f - context pointer will be written here 300 * @param provider - provider to use 301 * @param params - parameter string 302 * @param pool - process pool 303 * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE 304 * if the engine cannot be initialised. 305 */ 306static apr_status_t crypto_make(apr_crypto_t **ff, 307 const apr_crypto_driver_t *provider, const char *params, 308 apr_pool_t *pool) 309{ 310 apr_crypto_config_t *config = NULL; 311 apr_crypto_t *f; 312 313 f = apr_pcalloc(pool, sizeof(apr_crypto_t)); 314 if (!f) { 315 return APR_ENOMEM; 316 } 317 *ff = f; 318 f->pool = pool; 319 f->provider = provider; 320 config = f->config = apr_pcalloc(pool, sizeof(apr_crypto_config_t)); 321 if (!config) { 322 return APR_ENOMEM; 323 } 324 f->result = apr_pcalloc(pool, sizeof(apu_err_t)); 325 if (!f->result) { 326 return APR_ENOMEM; 327 } 328 329 f->types = apr_hash_make(pool); 330 if (!f->types) { 331 return APR_ENOMEM; 332 } 333 apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0])); 334 apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1])); 335 apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_types[2])); 336 apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_types[3])); 337 338 f->modes = apr_hash_make(pool); 339 if (!f->modes) { 340 return APR_ENOMEM; 341 } 342 apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0])); 343 apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1])); 344 345 apr_pool_cleanup_register(pool, f, crypto_cleanup_helper, 346 apr_pool_cleanup_null); 347 348 return APR_SUCCESS; 349 350} 351 352/** 353 * @brief Get a hash table of key types, keyed by the name of the type against 354 * a pointer to apr_crypto_block_key_type_t. 355 * 356 * @param types - hashtable of key types keyed to constants. 357 * @param f - encryption context 358 * @return APR_SUCCESS for success 359 */ 360static apr_status_t crypto_get_block_key_types(apr_hash_t **types, 361 const apr_crypto_t *f) 362{ 363 *types = f->types; 364 return APR_SUCCESS; 365} 366 367/** 368 * @brief Get a hash table of key modes, keyed by the name of the mode against 369 * a pointer to apr_crypto_block_key_mode_t. 370 * 371 * @param modes - hashtable of key modes keyed to constants. 372 * @param f - encryption context 373 * @return APR_SUCCESS for success 374 */ 375static apr_status_t crypto_get_block_key_modes(apr_hash_t **modes, 376 const apr_crypto_t *f) 377{ 378 *modes = f->modes; 379 return APR_SUCCESS; 380} 381 382/* 383 * Work out which mechanism to use. 384 */ 385static apr_status_t crypto_cipher_mechanism(apr_crypto_key_t *key, 386 const apr_crypto_block_key_type_e type, 387 const apr_crypto_block_key_mode_e mode, const int doPad) 388{ 389 390 /* decide on what cipher mechanism we will be using */ 391 switch (type) { 392 393 case (APR_KEY_3DES_192): 394 if (APR_MODE_CBC == mode) { 395 key->cipherOid = SEC_OID_DES_EDE3_CBC; 396 } 397 else if (APR_MODE_ECB == mode) { 398 return APR_ENOCIPHER; 399 /* No OID for CKM_DES3_ECB; */ 400 } 401 key->keyLength = 24; 402 break; 403 case (APR_KEY_AES_128): 404 if (APR_MODE_CBC == mode) { 405 key->cipherOid = SEC_OID_AES_128_CBC; 406 } 407 else { 408 key->cipherOid = SEC_OID_AES_128_ECB; 409 } 410 key->keyLength = 16; 411 break; 412 case (APR_KEY_AES_192): 413 if (APR_MODE_CBC == mode) { 414 key->cipherOid = SEC_OID_AES_192_CBC; 415 } 416 else { 417 key->cipherOid = SEC_OID_AES_192_ECB; 418 } 419 key->keyLength = 24; 420 break; 421 case (APR_KEY_AES_256): 422 if (APR_MODE_CBC == mode) { 423 key->cipherOid = SEC_OID_AES_256_CBC; 424 } 425 else { 426 key->cipherOid = SEC_OID_AES_256_ECB; 427 } 428 key->keyLength = 32; 429 break; 430 default: 431 /* unknown key type, give up */ 432 return APR_EKEYTYPE; 433 } 434 435 /* AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD */ 436 key->cipherMech = PK11_AlgtagToMechanism(key->cipherOid); 437 if (key->cipherMech == CKM_INVALID_MECHANISM) { 438 return APR_ENOCIPHER; 439 } 440 if (doPad) { 441 CK_MECHANISM_TYPE paddedMech; 442 paddedMech = PK11_GetPadMechanism(key->cipherMech); 443 if (CKM_INVALID_MECHANISM == paddedMech 444 || key->cipherMech == paddedMech) { 445 return APR_EPADDING; 446 } 447 key->cipherMech = paddedMech; 448 } 449 450 key->ivSize = PK11_GetIVLength(key->cipherMech); 451 452 return APR_SUCCESS; 453} 454 455/** 456 * @brief Create a key from the provided secret or passphrase. The key is cleaned 457 * up when the context is cleaned, and may be reused with multiple encryption 458 * or decryption operations. 459 * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If 460 * *key is not NULL, *key must point at a previously created structure. 461 * @param key The key returned, see note. 462 * @param rec The key record, from which the key will be derived. 463 * @param f The context to use. 464 * @param p The pool to use. 465 * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend 466 * error occurred while generating the key. APR_ENOCIPHER if the type or mode 467 * is not supported by the particular backend. APR_EKEYTYPE if the key type is 468 * not known. APR_EPADDING if padding was requested but is not supported. 469 * APR_ENOTIMPL if not implemented. 470 */ 471static apr_status_t crypto_key(apr_crypto_key_t **k, 472 const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p) 473{ 474 apr_status_t rv = APR_SUCCESS; 475 PK11SlotInfo *slot, *tslot; 476 PK11SymKey *tkey; 477 SECItem secretItem; 478 SECItem wrappedItem; 479 SECItem *secParam; 480 PK11Context *ctx; 481 SECStatus s; 482 SECItem passItem; 483 SECItem saltItem; 484 SECAlgorithmID *algid; 485 void *wincx = NULL; /* what is wincx? */ 486 apr_crypto_key_t *key; 487 int blockSize; 488 int remainder; 489 490 key = *k; 491 if (!key) { 492 *k = key = apr_pcalloc(p, sizeof *key); 493 if (!key) { 494 return APR_ENOMEM; 495 } 496 apr_pool_cleanup_register(p, key, crypto_key_cleanup, 497 apr_pool_cleanup_null); 498 } 499 500 key->f = f; 501 key->provider = f->provider; 502 503 /* decide on what cipher mechanism we will be using */ 504 rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad); 505 if (APR_SUCCESS != rv) { 506 return rv; 507 } 508 509 switch (rec->ktype) { 510 511 case APR_CRYPTO_KTYPE_PASSPHRASE: { 512 513 /* Turn the raw passphrase and salt into SECItems */ 514 passItem.data = (unsigned char*) rec->k.passphrase.pass; 515 passItem.len = rec->k.passphrase.passLen; 516 saltItem.data = (unsigned char*) rec->k.passphrase.salt; 517 saltItem.len = rec->k.passphrase.saltLen; 518 519 /* generate the key */ 520 /* pbeAlg and cipherAlg are the same. */ 521 algid = PK11_CreatePBEV2AlgorithmID(key->cipherOid, key->cipherOid, 522 SEC_OID_HMAC_SHA1, key->keyLength, 523 rec->k.passphrase.iterations, &saltItem); 524 if (algid) { 525 slot = PK11_GetBestSlot(key->cipherMech, wincx); 526 if (slot) { 527 key->symKey = PK11_PBEKeyGen(slot, algid, &passItem, PR_FALSE, 528 wincx); 529 PK11_FreeSlot(slot); 530 } 531 SECOID_DestroyAlgorithmID(algid, PR_TRUE); 532 } 533 534 break; 535 } 536 537 case APR_CRYPTO_KTYPE_SECRET: { 538 539 /* 540 * NSS is by default in FIPS mode, which disallows the use of unencrypted 541 * symmetrical keys. As per http://permalink.gmane.org/gmane.comp.mozilla.crypto/7947 542 * we do the following: 543 * 544 * 1. Generate a (temporary) symmetric key in NSS. 545 * 2. Use that symmetric key to encrypt your symmetric key as data. 546 * 3. Unwrap your wrapped symmetric key, using the symmetric key 547 * you generated in Step 1 as the unwrapping key. 548 * 549 * http://permalink.gmane.org/gmane.comp.mozilla.crypto/7947 550 */ 551 552 /* generate the key */ 553 slot = PK11_GetBestSlot(key->cipherMech, NULL); 554 if (slot) { 555 unsigned char data[BUFFER_SIZE]; 556 557 /* sanity check - key correct size? */ 558 if (rec->k.secret.secretLen != key->keyLength) { 559 PK11_FreeSlot(slot); 560 return APR_EKEYLENGTH; 561 } 562 563 tslot = PK11_GetBestSlot(CKM_AES_ECB, NULL); 564 if (tslot) { 565 566 /* generate a temporary wrapping key */ 567 tkey = PK11_KeyGen(tslot, CKM_AES_ECB, 0, PK11_GetBestKeyLength(tslot, CKM_AES_ECB), 0); 568 569 /* prepare the key to wrap */ 570 secretItem.data = (unsigned char *) rec->k.secret.secret; 571 secretItem.len = rec->k.secret.secretLen; 572 573 /* ensure our key matches the blocksize */ 574 secParam = PK11_GenerateNewParam(CKM_AES_ECB, tkey); 575 blockSize = PK11_GetBlockSize(CKM_AES_ECB, secParam); 576 remainder = rec->k.secret.secretLen % blockSize; 577 if (remainder) { 578 secretItem.data = 579 apr_pcalloc(p, rec->k.secret.secretLen + remainder); 580 apr_crypto_clear(p, secretItem.data, 581 rec->k.secret.secretLen); 582 memcpy(secretItem.data, rec->k.secret.secret, 583 rec->k.secret.secretLen); 584 secretItem.len += remainder; 585 } 586 587 /* prepare a space for the wrapped key */ 588 wrappedItem.data = data; 589 590 /* wrap the key */ 591 ctx = PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, tkey, 592 secParam); 593 if (ctx) { 594 s = PK11_CipherOp(ctx, wrappedItem.data, 595 (int *) (&wrappedItem.len), BUFFER_SIZE, 596 secretItem.data, secretItem.len); 597 if (s == SECSuccess) { 598 599 /* unwrap the key again */ 600 key->symKey = PK11_UnwrapSymKeyWithFlags(tkey, 601 CKM_AES_ECB, NULL, &wrappedItem, 602 key->cipherMech, CKA_ENCRYPT, 603 rec->k.secret.secretLen, 0); 604 605 } 606 607 PK11_DestroyContext(ctx, PR_TRUE); 608 } 609 610 /* clean up */ 611 SECITEM_FreeItem(secParam, PR_TRUE); 612 PK11_FreeSymKey(tkey); 613 PK11_FreeSlot(tslot); 614 615 } 616 617 PK11_FreeSlot(slot); 618 } 619 620 break; 621 } 622 623 default: { 624 625 return APR_ENOKEY; 626 627 } 628 } 629 630 /* sanity check? */ 631 if (!key->symKey) { 632 PRErrorCode perr = PORT_GetError(); 633 if (perr) { 634 f->result->rc = perr; 635 f->result->msg = PR_ErrorToName(perr); 636 rv = APR_ENOKEY; 637 } 638 } 639 640 return rv; 641} 642 643/** 644 * @brief Create a key from the given passphrase. By default, the PBKDF2 645 * algorithm is used to generate the key from the passphrase. It is expected 646 * that the same pass phrase will generate the same key, regardless of the 647 * backend crypto platform used. The key is cleaned up when the context 648 * is cleaned, and may be reused with multiple encryption or decryption 649 * operations. 650 * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If 651 * *key is not NULL, *key must point at a previously created structure. 652 * @param key The key returned, see note. 653 * @param ivSize The size of the initialisation vector will be returned, based 654 * on whether an IV is relevant for this type of crypto. 655 * @param pass The passphrase to use. 656 * @param passLen The passphrase length in bytes 657 * @param salt The salt to use. 658 * @param saltLen The salt length in bytes 659 * @param type 3DES_192, AES_128, AES_192, AES_256. 660 * @param mode Electronic Code Book / Cipher Block Chaining. 661 * @param doPad Pad if necessary. 662 * @param iterations Iteration count 663 * @param f The context to use. 664 * @param p The pool to use. 665 * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend 666 * error occurred while generating the key. APR_ENOCIPHER if the type or mode 667 * is not supported by the particular backend. APR_EKEYTYPE if the key type is 668 * not known. APR_EPADDING if padding was requested but is not supported. 669 * APR_ENOTIMPL if not implemented. 670 */ 671static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize, 672 const char *pass, apr_size_t passLen, const unsigned char * salt, 673 apr_size_t saltLen, const apr_crypto_block_key_type_e type, 674 const apr_crypto_block_key_mode_e mode, const int doPad, 675 const int iterations, const apr_crypto_t *f, apr_pool_t *p) 676{ 677 apr_status_t rv = APR_SUCCESS; 678 PK11SlotInfo * slot; 679 SECItem passItem; 680 SECItem saltItem; 681 SECAlgorithmID *algid; 682 void *wincx = NULL; /* what is wincx? */ 683 apr_crypto_key_t *key = *k; 684 685 if (!key) { 686 *k = key = apr_pcalloc(p, sizeof *key); 687 if (!key) { 688 return APR_ENOMEM; 689 } 690 apr_pool_cleanup_register(p, key, crypto_key_cleanup, 691 apr_pool_cleanup_null); 692 } 693 694 key->f = f; 695 key->provider = f->provider; 696 697 /* decide on what cipher mechanism we will be using */ 698 rv = crypto_cipher_mechanism(key, type, mode, doPad); 699 if (APR_SUCCESS != rv) { 700 return rv; 701 } 702 703 /* Turn the raw passphrase and salt into SECItems */ 704 passItem.data = (unsigned char*) pass; 705 passItem.len = passLen; 706 saltItem.data = (unsigned char*) salt; 707 saltItem.len = saltLen; 708 709 /* generate the key */ 710 /* pbeAlg and cipherAlg are the same. */ 711 algid = PK11_CreatePBEV2AlgorithmID(key->cipherOid, key->cipherOid, 712 SEC_OID_HMAC_SHA1, key->keyLength, iterations, &saltItem); 713 if (algid) { 714 slot = PK11_GetBestSlot(key->cipherMech, wincx); 715 if (slot) { 716 key->symKey = PK11_PBEKeyGen(slot, algid, &passItem, PR_FALSE, 717 wincx); 718 PK11_FreeSlot(slot); 719 } 720 SECOID_DestroyAlgorithmID(algid, PR_TRUE); 721 } 722 723 /* sanity check? */ 724 if (!key->symKey) { 725 PRErrorCode perr = PORT_GetError(); 726 if (perr) { 727 f->result->rc = perr; 728 f->result->msg = PR_ErrorToName(perr); 729 rv = APR_ENOKEY; 730 } 731 } 732 733 if (ivSize) { 734 *ivSize = key->ivSize; 735 } 736 737 return rv; 738} 739 740/** 741 * @brief Initialise a context for encrypting arbitrary data using the given key. 742 * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If 743 * *ctx is not NULL, *ctx must point at a previously created structure. 744 * @param ctx The block context returned, see note. 745 * @param iv Optional initialisation vector. If the buffer pointed to is NULL, 746 * an IV will be created at random, in space allocated from the pool. 747 * If the buffer pointed to is not NULL, the IV in the buffer will be 748 * used. 749 * @param key The key structure. 750 * @param blockSize The block size of the cipher. 751 * @param p The pool to use. 752 * @return Returns APR_ENOIV if an initialisation vector is required but not specified. 753 * Returns APR_EINIT if the backend failed to initialise the context. Returns 754 * APR_ENOTIMPL if not implemented. 755 */ 756static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx, 757 const unsigned char **iv, const apr_crypto_key_t *key, 758 apr_size_t *blockSize, apr_pool_t *p) 759{ 760 PRErrorCode perr; 761 SECItem ivItem; 762 unsigned char * usedIv; 763 apr_crypto_block_t *block = *ctx; 764 if (!block) { 765 *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t)); 766 } 767 if (!block) { 768 return APR_ENOMEM; 769 } 770 block->f = key->f; 771 block->pool = p; 772 block->provider = key->provider; 773 774 apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper, 775 apr_pool_cleanup_null); 776 777 if (key->ivSize) { 778 if (iv == NULL) { 779 return APR_ENOIV; 780 } 781 if (*iv == NULL) { 782 SECStatus s; 783 usedIv = apr_pcalloc(p, key->ivSize); 784 if (!usedIv) { 785 return APR_ENOMEM; 786 } 787 apr_crypto_clear(p, usedIv, key->ivSize); 788 s = PK11_GenerateRandom(usedIv, key->ivSize); 789 if (s != SECSuccess) { 790 return APR_ENOIV; 791 } 792 *iv = usedIv; 793 } 794 else { 795 usedIv = (unsigned char *) *iv; 796 } 797 ivItem.data = usedIv; 798 ivItem.len = key->ivSize; 799 block->secParam = PK11_ParamFromIV(key->cipherMech, &ivItem); 800 } 801 else { 802 block->secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey); 803 } 804 block->blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam); 805 block->ctx = PK11_CreateContextBySymKey(key->cipherMech, CKA_ENCRYPT, 806 key->symKey, block->secParam); 807 808 /* did an error occur? */ 809 perr = PORT_GetError(); 810 if (perr || !block->ctx) { 811 key->f->result->rc = perr; 812 key->f->result->msg = PR_ErrorToName(perr); 813 return APR_EINIT; 814 } 815 816 if (blockSize) { 817 *blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam); 818 } 819 820 return APR_SUCCESS; 821 822} 823 824/** 825 * @brief Encrypt data provided by in, write it to out. 826 * @note The number of bytes written will be written to outlen. If 827 * out is NULL, outlen will contain the maximum size of the 828 * buffer needed to hold the data, including any data 829 * generated by apr_crypto_block_encrypt_finish below. If *out points 830 * to NULL, a buffer sufficiently large will be created from 831 * the pool provided. If *out points to a not-NULL value, this 832 * value will be used as a buffer instead. 833 * @param out Address of a buffer to which data will be written, 834 * see note. 835 * @param outlen Length of the output will be written here. 836 * @param in Address of the buffer to read. 837 * @param inlen Length of the buffer to read. 838 * @param ctx The block context to use. 839 * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if 840 * not implemented. 841 */ 842static apr_status_t crypto_block_encrypt(unsigned char **out, 843 apr_size_t *outlen, const unsigned char *in, apr_size_t inlen, 844 apr_crypto_block_t *block) 845{ 846 847 unsigned char *buffer; 848 int outl = (int) *outlen; 849 SECStatus s; 850 if (!out) { 851 *outlen = inlen + block->blockSize; 852 return APR_SUCCESS; 853 } 854 if (!*out) { 855 buffer = apr_palloc(block->pool, inlen + block->blockSize); 856 if (!buffer) { 857 return APR_ENOMEM; 858 } 859 apr_crypto_clear(block->pool, buffer, inlen + block->blockSize); 860 *out = buffer; 861 } 862 863 s = PK11_CipherOp(block->ctx, *out, &outl, inlen, (unsigned char*) in, 864 inlen); 865 if (s != SECSuccess) { 866 PRErrorCode perr = PORT_GetError(); 867 if (perr) { 868 block->f->result->rc = perr; 869 block->f->result->msg = PR_ErrorToName(perr); 870 } 871 return APR_ECRYPT; 872 } 873 *outlen = outl; 874 875 return APR_SUCCESS; 876 877} 878 879/** 880 * @brief Encrypt final data block, write it to out. 881 * @note If necessary the final block will be written out after being 882 * padded. Typically the final block will be written to the 883 * same buffer used by apr_crypto_block_encrypt, offset by the 884 * number of bytes returned as actually written by the 885 * apr_crypto_block_encrypt() call. After this call, the context 886 * is cleaned and can be reused by apr_crypto_block_encrypt_init(). 887 * @param out Address of a buffer to which data will be written. This 888 * buffer must already exist, and is usually the same 889 * buffer used by apr_evp_crypt(). See note. 890 * @param outlen Length of the output will be written here. 891 * @param ctx The block context to use. 892 * @return APR_ECRYPT if an error occurred. 893 * @return APR_EPADDING if padding was enabled and the block was incorrectly 894 * formatted. 895 * @return APR_ENOTIMPL if not implemented. 896 */ 897static apr_status_t crypto_block_encrypt_finish(unsigned char *out, 898 apr_size_t *outlen, apr_crypto_block_t *block) 899{ 900 901 apr_status_t rv = APR_SUCCESS; 902 unsigned int outl = *outlen; 903 904 SECStatus s = PK11_DigestFinal(block->ctx, out, &outl, block->blockSize); 905 *outlen = outl; 906 907 if (s != SECSuccess) { 908 PRErrorCode perr = PORT_GetError(); 909 if (perr) { 910 block->f->result->rc = perr; 911 block->f->result->msg = PR_ErrorToName(perr); 912 } 913 rv = APR_ECRYPT; 914 } 915 crypto_block_cleanup(block); 916 917 return rv; 918 919} 920 921/** 922 * @brief Initialise a context for decrypting arbitrary data using the given key. 923 * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If 924 * *ctx is not NULL, *ctx must point at a previously created structure. 925 * @param ctx The block context returned, see note. 926 * @param blockSize The block size of the cipher. 927 * @param iv Optional initialisation vector. If the buffer pointed to is NULL, 928 * an IV will be created at random, in space allocated from the pool. 929 * If the buffer is not NULL, the IV in the buffer will be used. 930 * @param key The key structure. 931 * @param p The pool to use. 932 * @return Returns APR_ENOIV if an initialisation vector is required but not specified. 933 * Returns APR_EINIT if the backend failed to initialise the context. Returns 934 * APR_ENOTIMPL if not implemented. 935 */ 936static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx, 937 apr_size_t *blockSize, const unsigned char *iv, 938 const apr_crypto_key_t *key, apr_pool_t *p) 939{ 940 PRErrorCode perr; 941 apr_crypto_block_t *block = *ctx; 942 if (!block) { 943 *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t)); 944 } 945 if (!block) { 946 return APR_ENOMEM; 947 } 948 block->f = key->f; 949 block->pool = p; 950 block->provider = key->provider; 951 952 apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper, 953 apr_pool_cleanup_null); 954 955 if (key->ivSize) { 956 SECItem ivItem; 957 if (iv == NULL) { 958 return APR_ENOIV; /* Cannot initialise without an IV */ 959 } 960 ivItem.data = (unsigned char*) iv; 961 ivItem.len = key->ivSize; 962 block->secParam = PK11_ParamFromIV(key->cipherMech, &ivItem); 963 } 964 else { 965 block->secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey); 966 } 967 block->blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam); 968 block->ctx = PK11_CreateContextBySymKey(key->cipherMech, CKA_DECRYPT, 969 key->symKey, block->secParam); 970 971 /* did an error occur? */ 972 perr = PORT_GetError(); 973 if (perr || !block->ctx) { 974 key->f->result->rc = perr; 975 key->f->result->msg = PR_ErrorToName(perr); 976 return APR_EINIT; 977 } 978 979 if (blockSize) { 980 *blockSize = PK11_GetBlockSize(key->cipherMech, block->secParam); 981 } 982 983 return APR_SUCCESS; 984 985} 986 987/** 988 * @brief Decrypt data provided by in, write it to out. 989 * @note The number of bytes written will be written to outlen. If 990 * out is NULL, outlen will contain the maximum size of the 991 * buffer needed to hold the data, including any data 992 * generated by apr_crypto_block_decrypt_finish below. If *out points 993 * to NULL, a buffer sufficiently large will be created from 994 * the pool provided. If *out points to a not-NULL value, this 995 * value will be used as a buffer instead. 996 * @param out Address of a buffer to which data will be written, 997 * see note. 998 * @param outlen Length of the output will be written here. 999 * @param in Address of the buffer to read. 1000 * @param inlen Length of the buffer to read. 1001 * @param ctx The block context to use. 1002 * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if 1003 * not implemented. 1004 */ 1005static apr_status_t crypto_block_decrypt(unsigned char **out, 1006 apr_size_t *outlen, const unsigned char *in, apr_size_t inlen, 1007 apr_crypto_block_t *block) 1008{ 1009 1010 unsigned char *buffer; 1011 int outl = (int) *outlen; 1012 SECStatus s; 1013 if (!out) { 1014 *outlen = inlen + block->blockSize; 1015 return APR_SUCCESS; 1016 } 1017 if (!*out) { 1018 buffer = apr_palloc(block->pool, inlen + block->blockSize); 1019 if (!buffer) { 1020 return APR_ENOMEM; 1021 } 1022 apr_crypto_clear(block->pool, buffer, inlen + block->blockSize); 1023 *out = buffer; 1024 } 1025 1026 s = PK11_CipherOp(block->ctx, *out, &outl, inlen, (unsigned char*) in, 1027 inlen); 1028 if (s != SECSuccess) { 1029 PRErrorCode perr = PORT_GetError(); 1030 if (perr) { 1031 block->f->result->rc = perr; 1032 block->f->result->msg = PR_ErrorToName(perr); 1033 } 1034 return APR_ECRYPT; 1035 } 1036 *outlen = outl; 1037 1038 return APR_SUCCESS; 1039 1040} 1041 1042/** 1043 * @brief Decrypt final data block, write it to out. 1044 * @note If necessary the final block will be written out after being 1045 * padded. Typically the final block will be written to the 1046 * same buffer used by apr_crypto_block_decrypt, offset by the 1047 * number of bytes returned as actually written by the 1048 * apr_crypto_block_decrypt() call. After this call, the context 1049 * is cleaned and can be reused by apr_crypto_block_decrypt_init(). 1050 * @param out Address of a buffer to which data will be written. This 1051 * buffer must already exist, and is usually the same 1052 * buffer used by apr_evp_crypt(). See note. 1053 * @param outlen Length of the output will be written here. 1054 * @param ctx The block context to use. 1055 * @return APR_ECRYPT if an error occurred. 1056 * @return APR_EPADDING if padding was enabled and the block was incorrectly 1057 * formatted. 1058 * @return APR_ENOTIMPL if not implemented. 1059 */ 1060static apr_status_t crypto_block_decrypt_finish(unsigned char *out, 1061 apr_size_t *outlen, apr_crypto_block_t *block) 1062{ 1063 1064 apr_status_t rv = APR_SUCCESS; 1065 unsigned int outl = *outlen; 1066 1067 SECStatus s = PK11_DigestFinal(block->ctx, out, &outl, block->blockSize); 1068 *outlen = outl; 1069 1070 if (s != SECSuccess) { 1071 PRErrorCode perr = PORT_GetError(); 1072 if (perr) { 1073 block->f->result->rc = perr; 1074 block->f->result->msg = PR_ErrorToName(perr); 1075 } 1076 rv = APR_ECRYPT; 1077 } 1078 crypto_block_cleanup(block); 1079 1080 return rv; 1081 1082} 1083 1084/** 1085 * NSS module. 1086 */ 1087APU_MODULE_DECLARE_DATA const apr_crypto_driver_t apr_crypto_nss_driver = { 1088 "nss", crypto_init, crypto_make, crypto_get_block_key_types, 1089 crypto_get_block_key_modes, crypto_passphrase, 1090 crypto_block_encrypt_init, crypto_block_encrypt, 1091 crypto_block_encrypt_finish, crypto_block_decrypt_init, 1092 crypto_block_decrypt, crypto_block_decrypt_finish, 1093 crypto_block_cleanup, crypto_cleanup, crypto_shutdown, crypto_error, 1094 crypto_key 1095}; 1096 1097#endif 1098