1/* 2 * Copyright (c) 2003,2011-2012,2014 Apple Inc. All Rights Reserved. 3 * 4 * The contents of this file constitute Original Code as defined in and are 5 * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 * You may not use this file except in compliance with the License. Please obtain 7 * a copy of the License at http://www.apple.com/publicsource and read it before 8 * using this file. 9 * 10 * This Original Code and all software distributed under the License are 11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 15 * specific language governing rights and limitations under the License. 16 */ 17 18 19/* 20 * opensslAsn1.h - ANS1 encode/decode of openssl object, libssnasn1 version 21 */ 22#include "opensslAsn1.h" 23#include "BinaryKey.h" 24#include "AppleCSPUtils.h" 25#include "opensshCoding.h" 26#include <Security/osKeyTemplates.h> 27#include <openssl/err.h> 28#include <openssl/bn.h> 29#include <openssl/crypto.h> 30 31#include <security_asn1/SecNssCoder.h> 32#include <security_asn1/secerr.h> 33#include <Security/keyTemplates.h> 34#include <security_utilities/debugging.h> 35#include <Security/oidsalg.h> 36#include <Security/SecAsn1Templates.h> 37 38#include <assert.h> 39 40#define sslAsn1Debug(args...) secdebug("sslAsn1", ##args) 41 42#ifndef NDEBUG 43/* set to 1 to see all ASN related errors */ 44#define LOG_ASN_ERRORS 0 45#else 46#define LOG_ASN_ERRORS 0 47#endif 48 49#if LOG_ASN_ERRORS 50#include <stdio.h> 51#include <security_asn1/secerr.h> 52 53static void logAsnErr( 54 const char *op, 55 PRErrorCode perr) 56{ 57 printf("Error on %s: %s\n", op, SECErrorString(perr)); 58} 59#else 60#define logAsnErr(op, perr) 61#endif /* LOG_ASN_ERRORS */ 62 63/* CSSM_DATA --> BIGNUM */ 64BIGNUM *cssmDataToBn( 65 const CSSM_DATA &cdata) 66{ 67 BIGNUM *bn = BN_new(); 68 BIGNUM *rtn; 69 70 rtn = BN_bin2bn(cdata.Data, (int)cdata.Length, bn); 71 if(rtn == NULL) { 72 BN_free(bn); 73 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); 74 } 75 return bn; 76} 77 78/* BIGNUM --> CSSM_DATA, mallocing from a SecNssCoder's PL_ArenaPool */ 79void bnToCssmData( 80 const BIGNUM *bn, 81 CSSM_DATA &cdata, 82 SecNssCoder &coder) 83{ 84 assert(bn != NULL); 85 unsigned numBytes = BN_num_bytes(bn); 86 cdata.Data = (uint8 *)coder.malloc(numBytes); 87 if(cdata.Data == NULL) { 88 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); 89 } 90 cdata.Length = numBytes; 91 BN_bn2bin(bn, cdata.Data); 92} 93 94/* 95 * CSSM_DATA --> unsigned int 96 */ 97unsigned cssmDataToInt( 98 const CSSM_DATA &cdata) 99{ 100 if((cdata.Length == 0) || (cdata.Data == NULL)) { 101 return 0; 102 } 103 unsigned len = (unsigned)cdata.Length; 104 if(len > sizeof(int)) { 105 logAsnErr("cssmDataToInt: Length error (%u)", len); 106 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS); 107 } 108 109 unsigned rtn = 0; 110 uint8 *cp = cdata.Data; 111 for(unsigned i=0; i<len; i++) { 112 rtn = (rtn << 8) | *cp++; 113 } 114 return rtn; 115} 116 117/* 118 * unsigned int --> CSSM_DATA, mallocing from an SecNssCoder 119 */ 120void intToCssmData( 121 unsigned num, 122 CSSM_DATA &cdata, 123 SecNssCoder &coder) 124{ 125 unsigned len = 0; 126 127 if(num < 0x100) { 128 len = 1; 129 } 130 else if(num < 0x10000) { 131 len = 2; 132 } 133 else if(num < 0x1000000) { 134 len = 3; 135 } 136 else { 137 len = 4; 138 } 139 cdata.Data = (uint8 *)coder.malloc(len); 140 cdata.Length = len; 141 uint8 *cp = &cdata.Data[len - 1]; 142 for(unsigned i=0; i<len; i++) { 143 *cp-- = num & 0xff; 144 num >>= 8; 145 } 146} 147 148/* 149 * Set up a encoded NULL for AlgorithmIdentifier.parameters, 150 * required for RSA 151 */ 152static void nullAlgParams( 153 CSSM_X509_ALGORITHM_IDENTIFIER &algId) 154{ 155 static const uint8 encNull[2] = { SEC_ASN1_NULL, 0 }; 156 CSSM_DATA encNullData; 157 encNullData.Data = (uint8 *)encNull; 158 encNullData.Length = 2; 159 160 algId.parameters = encNullData; 161} 162 163#pragma mark - 164#pragma mark *** RSA key encode/decode *** 165 166/* 167 * DER encode/decode RSA keys in various formats. 168 * 169 * Public key, CSSM_KEYBLOB_RAW_FORMAT_PKCS1 170 * -- compatible with BSAFE 171 * -- used for CSSM_KEYBLOB_RAW_FORMAT_DIGEST on both keys 172 */ 173static CSSM_RETURN RSAPublicKeyDecodePKCS1( 174 SecNssCoder &coder, 175 RSA *openKey, 176 void *p, 177 size_t length) 178{ 179 NSS_RSAPublicKeyPKCS1 nssPubKey; 180 181 memset(&nssPubKey, 0, sizeof(nssPubKey)); 182 PRErrorCode perr = coder.decode(p, length, 183 kSecAsn1RSAPublicKeyPKCS1Template, &nssPubKey); 184 if(perr) { 185 logAsnErr("decode(RSAPublicKeyPKCS1)", perr); 186 return CSSMERR_CSP_INVALID_KEY; 187 } 188 189 try { 190 openKey->n = cssmDataToBn(nssPubKey.modulus); 191 openKey->e = cssmDataToBn(nssPubKey.publicExponent); 192 } 193 catch(...) { 194 return CSSMERR_CSP_MEMORY_ERROR; 195 } 196 return 0; 197} 198 199static CSSM_RETURN RSAPublicKeyEncodePKCS1( 200 SecNssCoder &coder, 201 RSA *openKey, 202 CssmOwnedData &encodedKey) 203{ 204 /* convert to NSS_RSAPublicKeyPKCS1 */ 205 NSS_RSAPublicKeyPKCS1 nssPubKey; 206 207 try { 208 bnToCssmData(openKey->n, nssPubKey.modulus, coder); 209 bnToCssmData(openKey->e, nssPubKey.publicExponent, coder); 210 } 211 catch(...) { 212 return CSSMERR_CSP_MEMORY_ERROR; 213 } 214 215 PRErrorCode prtn; 216 prtn = SecNssEncodeItemOdata(&nssPubKey, 217 kSecAsn1RSAPublicKeyPKCS1Template, encodedKey); 218 if(prtn) { 219 return CSSMERR_CSP_MEMORY_ERROR; 220 } 221 return CSSM_OK; 222} 223 224/* 225 * SubjectPublicKeyInfo, as used by openssl. 226 * The subjectPublicKey component is a PKCS1-style RSAPublicKey. 227 */ 228static CSSM_RETURN RSAPublicKeyDecodeX509( 229 SecNssCoder &coder, 230 RSA *openKey, 231 void *p, 232 CSSM_SIZE length, 233 /* mallocd/returned encoded alg params for OAEP key */ 234 uint8 **algParams, 235 CSSM_SIZE *algParamLen) 236{ 237 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO nssPubKeyInfo; 238 PRErrorCode perr; 239 240 memset(&nssPubKeyInfo, 0, sizeof(nssPubKeyInfo)); 241 perr = coder.decode(p, length, kSecAsn1SubjectPublicKeyInfoTemplate, 242 &nssPubKeyInfo); 243 if(perr) { 244 logAsnErr("decode(RSA SubjectPublicKeyInfo)", perr); 245 return CSSMERR_CSP_INVALID_KEY; 246 } 247 248 /* verify alg identifier */ 249 const CSSM_OID *oid = &nssPubKeyInfo.algorithm.algorithm; 250 if(!cspCompareCssmData(oid, &CSSMOID_RSA)) { 251 if(!cspCompareCssmData(oid, &CSSMOID_RSAWithOAEP)) { 252 sslAsn1Debug("RSAPublicKeyDecodeX509: bad OID"); 253 return CSSMERR_CSP_INVALID_KEY; 254 } 255 if(nssPubKeyInfo.algorithm.parameters.Data != NULL) { 256 CSSM_SIZE len = nssPubKeyInfo.algorithm.parameters.Length; 257 *algParams = (uint8 *)malloc(len); 258 memmove(*algParams, nssPubKeyInfo.algorithm.parameters.Data, len); 259 *algParamLen = len; 260 } 261 } 262 263 /* decode the raw bits */ 264 CSSM_DATA *pubKey = &nssPubKeyInfo.subjectPublicKey; 265 /* decoded length was in bits */ 266 pubKey->Length = (pubKey->Length + 7) / 8; 267 return RSAPublicKeyDecodePKCS1(coder, openKey, pubKey->Data, 268 pubKey->Length); 269} 270 271static CSSM_RETURN RSAPublicKeyEncodeX509( 272 SecNssCoder &coder, 273 RSA *openKey, 274 CssmOwnedData &encodedKey, 275 /* encoded alg params for OAEP key */ 276 uint8 *algParams, 277 uint32 algParamsLen) 278{ 279 CssmAutoData aData(Allocator::standard()); 280 CSSM_RETURN crtn; 281 282 /* First get an encoded PKCS1-style RSAPublicKey */ 283 crtn = RSAPublicKeyEncodePKCS1(coder, openKey, aData); 284 if(crtn) { 285 return crtn; 286 } 287 288 /* 289 * That's the AsnBits subjectPublicKey component of a 290 * SubjectPublicKeyInfo 291 */ 292 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO nssPubKeyInfo; 293 memset(&nssPubKeyInfo, 0, sizeof(nssPubKeyInfo)); 294 nssPubKeyInfo.subjectPublicKey.Data = (uint8 *)aData.data(); 295 nssPubKeyInfo.subjectPublicKey.Length = aData.length() * 8; 296 297 CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssPubKeyInfo.algorithm; 298 algId.algorithm = CSSMOID_RSA; 299 300 if(algParams) { 301 algId.parameters.Data = (uint8 *)algParams; 302 algId.parameters.Length = algParamsLen; 303 } 304 else { 305 /* NULL algorithm parameters */ 306 nullAlgParams(algId); 307 } 308 309 /* DER encode */ 310 PRErrorCode perr; 311 perr = SecNssEncodeItemOdata(&nssPubKeyInfo, 312 kSecAsn1SubjectPublicKeyInfoTemplate, encodedKey); 313 314 if(perr) { 315 logAsnErr("encode(RSA SubjectPublicKeyInfo)", perr); 316 return CSSMERR_CSP_MEMORY_ERROR; 317 } 318 return CSSM_OK; 319} 320 321/* 322 * RSA private key, PKCS1 format, used by openssl. 323 */ 324static CSSM_RETURN RSAPrivateKeyDecodePKCS1( 325 SecNssCoder &coder, 326 RSA *openKey, 327 void *p, 328 size_t length) 329{ 330 NSS_RSAPrivateKeyPKCS1 nssPrivKey; 331 PRErrorCode perr; 332 333 memset(&nssPrivKey, 0, sizeof(nssPrivKey)); 334 perr = coder.decode(p, length, kSecAsn1RSAPrivateKeyPKCS1Template, &nssPrivKey); 335 if(perr) { 336 logAsnErr("decode(RSAPrivateKeyPKCS)", perr); 337 return CSSMERR_CSP_INVALID_KEY; 338 } 339 340 /* convert nssPrivKey fields to RSA key fields */ 341 try { 342 openKey->version = cssmDataToInt(nssPrivKey.version); 343 openKey->n = cssmDataToBn(nssPrivKey.modulus); 344 openKey->e = cssmDataToBn(nssPrivKey.publicExponent); 345 openKey->d = cssmDataToBn(nssPrivKey.privateExponent); 346 openKey->p = cssmDataToBn(nssPrivKey.prime1); 347 openKey->q = cssmDataToBn(nssPrivKey.prime2); 348 openKey->dmp1 = cssmDataToBn(nssPrivKey.exponent1); 349 openKey->dmq1 = cssmDataToBn(nssPrivKey.exponent2); 350 openKey->iqmp = cssmDataToBn(nssPrivKey.coefficient); 351 } 352 catch(...) { 353 return CSSMERR_CSP_MEMORY_ERROR; 354 } 355 return 0; 356} 357 358static CSSM_RETURN RSAPrivateKeyEncodePKCS1( 359 SecNssCoder &coder, 360 RSA *openKey, 361 CssmOwnedData &encodedKey) 362{ 363 NSS_RSAPrivateKeyPKCS1 nssPrivKey; 364 PRErrorCode perr; 365 366 /* convert to NSS_RSAPrivateKeyPKCS1 */ 367 try { 368 intToCssmData(openKey->version, nssPrivKey.version, coder); 369 bnToCssmData(openKey->n, nssPrivKey.modulus, coder); 370 bnToCssmData(openKey->e, nssPrivKey.publicExponent, coder); 371 bnToCssmData(openKey->d, nssPrivKey.privateExponent, coder); 372 bnToCssmData(openKey->p, nssPrivKey.prime1, coder); 373 bnToCssmData(openKey->q, nssPrivKey.prime2, coder); 374 bnToCssmData(openKey->dmp1, nssPrivKey.exponent1, coder); 375 bnToCssmData(openKey->dmq1, nssPrivKey.exponent2, coder); 376 bnToCssmData(openKey->iqmp, nssPrivKey.coefficient, coder); 377 } 378 catch(...) { 379 /* ? */ 380 return CSSMERR_CSP_MEMORY_ERROR; 381 } 382 383 /* DER encode */ 384 perr = SecNssEncodeItemOdata(&nssPrivKey, kSecAsn1RSAPrivateKeyPKCS1Template, 385 encodedKey); 386 if(perr) { 387 logAsnErr("encode(RSAPrivateKeyPKCS1)", perr); 388 return CSSMERR_CSP_MEMORY_ERROR; 389 } 390 return CSSM_OK; 391} 392 393/* 394 * RSA private key, PKCS8, compatible with BSAFE. 395 */ 396static CSSM_RETURN RSAPrivateKeyDecodePKCS8( 397 SecNssCoder &coder, 398 RSA *openKey, 399 void *p, 400 CSSM_SIZE length, 401 /* mallocd/returned encoded alg params for OAEP key */ 402 uint8 **algParams, 403 CSSM_SIZE *algParamLen) 404{ 405 NSS_PrivateKeyInfo nssPrivKeyInfo; 406 PRErrorCode perr; 407 408 memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo)); 409 perr = coder.decode(p, length, kSecAsn1PrivateKeyInfoTemplate, &nssPrivKeyInfo); 410 if(perr) { 411 logAsnErr("decode(PrivateKeyInfo)", perr); 412 return CSSMERR_CSP_INVALID_KEY; 413 } 414 415 /* verify alg identifier */ 416 const CSSM_OID *oid = &nssPrivKeyInfo.algorithm.algorithm; 417 if(!cspCompareCssmData(oid, &CSSMOID_RSA)) { 418 if(!cspCompareCssmData(oid, &CSSMOID_RSAWithOAEP)) { 419 sslAsn1Debug("RSAPrivateKeyDecodePKCS8: bad OID"); 420 return CSSMERR_CSP_INVALID_KEY; 421 } 422 if(nssPrivKeyInfo.algorithm.parameters.Data != NULL) { 423 CSSM_SIZE len = nssPrivKeyInfo.algorithm.parameters.Length; 424 *algParams = (uint8 *)malloc(len); 425 memmove(*algParams, nssPrivKeyInfo.algorithm.parameters.Data, len); 426 *algParamLen = len; 427 } 428 } 429 430 /* 431 * nssPrivKeyInfo.privateKey is an octet string which needs 432 * subsequent decoding 433 */ 434 CSSM_DATA *privKey = &nssPrivKeyInfo.privateKey; 435 return RSAPrivateKeyDecodePKCS1(coder, openKey, 436 privKey->Data, privKey->Length); 437} 438 439static CSSM_RETURN RSAPrivateKeyEncodePKCS8( 440 SecNssCoder &coder, 441 RSA *openKey, 442 CssmOwnedData &encodedKey, 443 /* encoded alg params for OAEP key */ 444 uint8 *algParams, 445 uint32 algParamsLen) 446{ 447 448 /* First get PKCS1-style encoding */ 449 CssmAutoData aData(Allocator::standard()); 450 CSSM_RETURN crtn = RSAPrivateKeyEncodePKCS1(coder, openKey, aData); 451 if(crtn) { 452 return crtn; 453 } 454 455 /* that encoding is the privateKey field of a NSS_PrivateKeyInfo */ 456 NSS_PrivateKeyInfo nssPrivKeyInfo; 457 memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo)); 458 nssPrivKeyInfo.privateKey.Data = (uint8 *)aData.data(); 459 nssPrivKeyInfo.privateKey.Length = aData.length(); 460 461 CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssPrivKeyInfo.algorithm; 462 algId.algorithm = CSSMOID_RSA; 463 464 if(algParams) { 465 algId.parameters.Data = (uint8 *)algParams; 466 algId.parameters.Length = algParamsLen; 467 } 468 else { 469 /* NULL algorithm parameters */ 470 nullAlgParams(algId); 471 } 472 473 /* FIXME : attributes? */ 474 475 uint8 vers = 0; 476 nssPrivKeyInfo.version.Data = &vers; 477 nssPrivKeyInfo.version.Length = 1; 478 479 /* DER encode */ 480 PRErrorCode perr; 481 perr = SecNssEncodeItemOdata(&nssPrivKeyInfo, 482 kSecAsn1PrivateKeyInfoTemplate, encodedKey); 483 484 if(perr) { 485 logAsnErr("encode(RSA PrivateKeyInfo)", perr); 486 return CSSMERR_CSP_MEMORY_ERROR; 487 } 488 return CSSM_OK; 489} 490 491CSSM_RETURN RSAPublicKeyDecode( 492 RSA *openKey, 493 CSSM_KEYBLOB_FORMAT format, 494 void *p, 495 size_t length) 496{ 497 SecNssCoder coder; 498 499 switch(format) { 500 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: 501 return RSAPublicKeyDecodePKCS1(coder, openKey, p, length); 502 case CSSM_KEYBLOB_RAW_FORMAT_X509: 503 return RSAPublicKeyDecodeX509(coder, openKey, p, length, NULL, NULL); 504 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: 505 return RSAPublicKeyDecodeOpenSSH1(openKey, p, length); 506 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: 507 return RSAPublicKeyDecodeOpenSSH2(openKey, p, length); 508 default: 509 assert(0); 510 return CSSMERR_CSP_INTERNAL_ERROR; 511 } 512} 513 514CSSM_RETURN RSAPublicKeyEncode( 515 RSA *openKey, 516 CSSM_KEYBLOB_FORMAT format, 517 const CssmData &descData, 518 CssmOwnedData &encodedKey) 519{ 520 SecNssCoder coder; 521 522 switch(format) { 523 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: 524 return RSAPublicKeyEncodePKCS1(coder, openKey, encodedKey); 525 case CSSM_KEYBLOB_RAW_FORMAT_X509: 526 return RSAPublicKeyEncodeX509(coder, openKey, encodedKey, NULL, 0); 527 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: 528 return RSAPublicKeyEncodeOpenSSH1(openKey, descData, encodedKey); 529 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: 530 return RSAPublicKeyEncodeOpenSSH2(openKey, descData, encodedKey); 531 default: 532 assert(0); 533 return CSSMERR_CSP_INTERNAL_ERROR; 534 } 535} 536 537CSSM_RETURN RSAPrivateKeyDecode( 538 RSA *openKey, 539 CSSM_KEYBLOB_FORMAT format, 540 void *p, 541 size_t length) 542{ 543 SecNssCoder coder; 544 545 switch(format) { 546 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: 547 return RSAPrivateKeyDecodePKCS1(coder, openKey, p, length); 548 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: 549 return RSAPrivateKeyDecodePKCS8(coder, openKey, p, length, NULL, NULL); 550 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: 551 return RSAPrivateKeyDecodeOpenSSH1(openKey, p, length); 552 default: 553 assert(0); 554 return CSSMERR_CSP_INTERNAL_ERROR; 555 } 556} 557 558CSSM_RETURN RSAPrivateKeyEncode( 559 RSA *openKey, 560 CSSM_KEYBLOB_FORMAT format, 561 const CssmData &descData, 562 CssmOwnedData &encodedKey) 563{ 564 SecNssCoder coder; 565 566 switch(format) { 567 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: 568 return RSAPrivateKeyEncodePKCS1(coder, openKey, encodedKey); 569 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: 570 return RSAPrivateKeyEncodePKCS8(coder, openKey, encodedKey, NULL, 0); 571 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: 572 return RSAPrivateKeyEncodeOpenSSH1(openKey, descData, encodedKey); 573 default: 574 assert(0); 575 return CSSMERR_CSP_INTERNAL_ERROR; 576 } 577} 578 579CSSM_RETURN RSAOAEPPrivateKeyEncode( 580 RSA *openKey, 581 const CSSM_DATA *label, 582 CssmOwnedData &encodedKey) 583{ 584 SecNssCoder coder; 585 CSSM_DATA encodedParams = {0, NULL}; 586 /* TBD encode the label into a RSAES-OAEP-params */ 587 588 return RSAPrivateKeyEncodePKCS8(coder, openKey, encodedKey, encodedParams.Data, (unsigned int)encodedParams.Length); 589} 590 591CSSM_RETURN RSAOAEPPublicKeyEncode( 592 RSA *openKey, 593 const CSSM_DATA *label, 594 CssmOwnedData &encodedKey) 595{ 596 SecNssCoder coder; 597 CSSM_DATA encodedParams = {0, NULL}; 598 /* TBD encode the label into a RSAES-OAEP-params */ 599 600 return RSAPublicKeyEncodeX509(coder, openKey, encodedKey, encodedParams.Data, (unsigned int)encodedParams.Length); 601} 602 603CSSM_RETURN RSAOAEPPublicKeyDecode( 604 RSA *openKey, 605 void *p, 606 size_t length, 607 /* mallocd and returned label */ 608 CSSM_DATA *label) 609{ 610 SecNssCoder coder; 611 CSSM_RETURN crtn; 612 CSSM_DATA encodedParams = {0, NULL}; 613 614 crtn = RSAPublicKeyDecodeX509(coder, openKey, p, length, &encodedParams.Data, 615 &encodedParams.Length); 616 if(crtn) { 617 return crtn; 618 } 619 620 /* TBD - decode label from encoded alg params */ 621 label->Data = NULL; 622 label->Length = 0; 623 return CSSM_OK; 624} 625 626CSSM_RETURN RSAOAEPPrivateKeyDecode( 627 RSA *openKey, 628 void *p, 629 size_t length, 630 /* mallocd and returned label */ 631 CSSM_DATA *label) 632{ 633 SecNssCoder coder; 634 CSSM_RETURN crtn; 635 CSSM_DATA encodedParams = {0, NULL}; 636 637 crtn = RSAPrivateKeyDecodePKCS8(coder, openKey, p, length, &encodedParams.Data, 638 &encodedParams.Length); 639 if(crtn) { 640 return crtn; 641 } 642 643 /* TBD - decode label from encoded alg params */ 644 label->Data = NULL; 645 label->Length = 0; 646 return CSSM_OK; 647} 648 649#pragma mark - 650#pragma mark *** DSA key encode/decode *** 651 652/*** 653 *** DSA 654 ***/ 655 656/* NSS_DSAAlgorithmIdBSAFE <--> DSA->{p,g,q} */ 657static void dsaToNssAlgIdBSAFE( 658 const DSA *openKey, 659 NSS_DSAAlgorithmIdBSAFE &algId, 660 SecNssCoder &coder) 661{ 662 /* non-standard, BSAFE-specific OID */ 663 algId.algorithm = CSSMOID_DSA; // not mallocd 664 unsigned numBits = BN_num_bits(openKey->p); 665 intToCssmData(numBits, algId.params.keySizeInBits, coder); 666 bnToCssmData(openKey->p, algId.params.p, coder); 667 bnToCssmData(openKey->q, algId.params.q, coder); 668 bnToCssmData(openKey->g, algId.params.g, coder); 669} 670 671static CSSM_RETURN nssAlgIdToDsaBSAFE( 672 NSS_DSAAlgorithmIdBSAFE &algId, 673 DSA *openKey) 674{ 675 /* non-standard, BSAFE-specific OID */ 676 if(!cspCompareCssmData(&algId.algorithm, &CSSMOID_DSA)) { 677 sslAsn1Debug("nssAlgIdToDsaBSAFE: bad OID"); 678 return CSSMERR_CSP_INVALID_KEY; 679 } 680 openKey->p = cssmDataToBn(algId.params.p); 681 openKey->q = cssmDataToBn(algId.params.q); 682 openKey->g = cssmDataToBn(algId.params.g); 683 return CSSM_OK; 684} 685 686/* NSS_DSAAlgorithmIdX509 <--> DSA->{p,g,q} */ 687static void dsaToNssAlgIdX509( 688 const DSA *openKey, 689 NSS_DSAAlgorithmIdX509 &algId, 690 SecNssCoder &coder) 691{ 692 algId.algorithm = CSSMOID_DSA_CMS; // not mallocd 693 bnToCssmData(openKey->p, algId.params->p, coder); 694 bnToCssmData(openKey->q, algId.params->q, coder); 695 bnToCssmData(openKey->g, algId.params->g, coder); 696} 697 698static CSSM_RETURN nssAlgIdToDsaX509( 699 NSS_DSAAlgorithmIdX509 &algId, 700 DSA *openKey) 701{ 702 if(!cspCompareCssmData(&algId.algorithm, &CSSMOID_DSA_CMS) && 703 !cspCompareCssmData(&algId.algorithm, &CSSMOID_DSA_JDK)) { 704 sslAsn1Debug("nssAlgIdToDsaX509: bad OID"); 705 return CSSMERR_CSP_INVALID_KEY; 706 } 707 /* these might be absent per CMS */ 708 if(algId.params == NULL) { 709 return CSSM_OK; 710 } 711 openKey->p = cssmDataToBn(algId.params->p); 712 openKey->q = cssmDataToBn(algId.params->q); 713 openKey->g = cssmDataToBn(algId.params->g); 714 return CSSM_OK; 715} 716 717/* 718 * DSA public keys, FIPS186 format. 719 * Compatible with BSAFE. 720 */ 721static 722CSSM_RETURN DSAPublicKeyDecodeFIPS186( 723 SecNssCoder &coder, 724 DSA *openKey, 725 void *p, 726 size_t length) 727{ 728 NSS_DSAPublicKeyBSAFE nssPubKey; 729 PRErrorCode perr; 730 CSSM_RETURN crtn; 731 732 memset(&nssPubKey, 0, sizeof(nssPubKey)); 733 perr = coder.decode(p, length, kSecAsn1DSAPublicKeyBSAFETemplate, 734 &nssPubKey); 735 if(perr) { 736 logAsnErr("decode(DSAPublicKeyBSAFE)", perr); 737 return CSSMERR_CSP_INVALID_KEY; 738 } 739 740 /* BSAFE style DSA-specific alg params */ 741 NSS_DSAAlgorithmIdBSAFE &algId = nssPubKey.dsaAlg; 742 crtn = nssAlgIdToDsaBSAFE(algId, openKey); 743 if(crtn) { 744 return crtn; 745 } 746 747 /* inside of nssPubKey.publicKey is the DER-encoding of a 748 * ASN Integer; decoded length was in bits */ 749 nssPubKey.publicKey.Length = (nssPubKey.publicKey.Length + 7) / 8; 750 CSSM_DATA pubKeyBytes; 751 perr = coder.decodeItem(nssPubKey.publicKey, 752 kSecAsn1UnsignedIntegerTemplate, 753 &pubKeyBytes); 754 if(perr) { 755 logAsnErr("decode(NSS_DSAPublicKeyBSAFE.publicKey)", perr); 756 return CSSMERR_CSP_INVALID_KEY; 757 } 758 openKey->pub_key = cssmDataToBn(pubKeyBytes); 759 760 if(openKey->pub_key == NULL) { 761 return CSSMERR_CSP_INVALID_KEY; 762 } 763 return 0; 764} 765 766static 767CSSM_RETURN DSAPublicKeyEncodeFIPS186( 768 SecNssCoder &coder, 769 DSA *openKey, 770 CssmOwnedData &encodedKey) 771{ 772 try { 773 /* convert to NSS_DSAPublicKeyBSAFE */ 774 NSS_DSAPublicKeyBSAFE nssPubKey; 775 memset(&nssPubKey, 0, sizeof(nssPubKey)); 776 dsaToNssAlgIdBSAFE(openKey, nssPubKey.dsaAlg, coder); 777 778 /* 779 * publicKey is the DER-encoding of a ASN INTEGER wrapped in 780 * an AsnBits 781 */ 782 CSSM_DATA pubKeyRaw; 783 PRErrorCode perr; 784 bnToCssmData(openKey->pub_key, pubKeyRaw, coder); 785 perr = coder.encodeItem(&pubKeyRaw, kSecAsn1UnsignedIntegerTemplate, 786 nssPubKey.publicKey); 787 if(perr) { 788 logAsnErr("encodeItem(DSAPublicKeyBSAFE.publicKey)", perr); 789 return CSSMERR_CSP_MEMORY_ERROR; 790 } 791 nssPubKey.publicKey.Length *= 8; 792 793 /* DER encode */ 794 SecNssEncodeItemOdata(&nssPubKey, kSecAsn1DSAPublicKeyBSAFETemplate, 795 encodedKey); 796 return CSSM_OK; 797 } 798 catch(...) { 799 /* ? */ 800 return CSSMERR_CSP_MEMORY_ERROR; 801 } 802} 803 804/* 805 * DSA private keys, FIPS186 format. 806 * Compatible with BSAFE. 807 */ 808static 809CSSM_RETURN DSAPrivateKeyDecodeFIPS186( 810 SecNssCoder &coder, 811 DSA *openKey, 812 void *p, 813 unsigned length) 814{ 815 NSS_DSAPrivateKeyBSAFE nssPrivKeyInfo; 816 PRErrorCode perr; 817 818 memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo)); 819 perr = coder.decode(p, length, kSecAsn1DSAPrivateKeyBSAFETemplate, 820 &nssPrivKeyInfo); 821 if(perr) { 822 logAsnErr("decode(DSA PrivateKeyInfo)", perr); 823 return CSSMERR_CSP_INVALID_KEY; 824 } 825 826 CSSM_RETURN crtn = nssAlgIdToDsaBSAFE(nssPrivKeyInfo.dsaAlg, openKey); 827 if(crtn) { 828 return crtn; 829 } 830 831 /* nssPrivKeyInfo.privateKey is the DER-encoding of a 832 * DSAPrivateKeyOcts... */ 833 try { 834 PRErrorCode perr; 835 NSS_DSAPrivateKeyOcts keyOcts; 836 837 perr = coder.decodeItem(nssPrivKeyInfo.privateKey, 838 kSecAsn1DSAPrivateKeyOctsTemplate, &keyOcts); 839 if(perr) { 840 logAsnErr("decode(DSA PrivateKeyInfoOcts)", perr); 841 return CSSMERR_CSP_INVALID_KEY; 842 } 843 844 openKey->priv_key = cssmDataToBn(keyOcts.privateKey); 845 if(openKey->priv_key == NULL) { 846 return CSSMERR_CSP_INVALID_KEY; 847 } 848 return 0; 849 } 850 catch(...) { 851 return CSSMERR_CSP_INVALID_KEY; 852 } 853} 854 855static 856CSSM_RETURN DSAPrivateKeyEncodeFIPS186( 857 SecNssCoder &coder, 858 DSA *openKey, 859 CssmOwnedData &encodedKey) 860{ 861 try { 862 /* First convert into a NSS_DSAPrivateKeyBSAFE */ 863 NSS_DSAPrivateKeyBSAFE nssPrivKey; 864 intToCssmData(openKey->version, nssPrivKey.version, coder); 865 dsaToNssAlgIdBSAFE(openKey, nssPrivKey.dsaAlg, coder); 866 867 /* nssPrivKey.privateKey is the DER-encoding of one of these... */ 868 NSS_DSAPrivateKeyOcts privKeyOcts; 869 bnToCssmData(openKey->priv_key, privKeyOcts.privateKey, coder); 870 871 /* DER encode the privateKey portion into arena pool memory 872 * into NSS_DSAPrivateKeyPKCS8.privateKey */ 873 coder.encodeItem(&privKeyOcts, kSecAsn1DSAPrivateKeyOctsTemplate, 874 nssPrivKey.privateKey); 875 876 /* DER encode the whole thing */ 877 PRErrorCode perr; 878 perr = SecNssEncodeItemOdata(&nssPrivKey, 879 kSecAsn1DSAPrivateKeyBSAFETemplate, encodedKey); 880 return 0; 881 } 882 catch(...) { 883 /* ? */ 884 return CSSMERR_CSP_MEMORY_ERROR; 885 } 886} 887 888/* 889 * DSA private keys, PKCS8/SMIME format. 890 */ 891static 892CSSM_RETURN DSAPrivateKeyDecodePKCS8( 893 SecNssCoder &coder, 894 DSA *openKey, 895 void *p, 896 unsigned length) 897{ 898 NSS_DSAPrivateKeyPKCS8 nssPrivKeyInfo; 899 PRErrorCode perr; 900 901 memset(&nssPrivKeyInfo, 0, sizeof(nssPrivKeyInfo)); 902 perr = coder.decode(p, length, kSecAsn1DSAPrivateKeyPKCS8Template, 903 &nssPrivKeyInfo); 904 if(perr) { 905 logAsnErr("decode(DSA NSS_DSAPrivateKeyPKCS8)", perr); 906 return CSSMERR_CSP_INVALID_KEY; 907 } 908 909 CSSM_RETURN crtn = nssAlgIdToDsaX509(nssPrivKeyInfo.dsaAlg, openKey); 910 if(crtn) { 911 return crtn; 912 } 913 914 /* 915 * Post-decode, nssPrivKeyInfo.privateKey is the DER-encoding of a 916 * an ASN integer. 917 */ 918 try { 919 PRErrorCode perr; 920 CSSM_DATA privKeyInt = {0, NULL}; 921 922 perr = coder.decodeItem(nssPrivKeyInfo.privateKey, 923 kSecAsn1UnsignedIntegerTemplate, &privKeyInt); 924 if(perr) { 925 logAsnErr("decode(DSA nssPrivKeyInfo.privateKey)", perr); 926 return CSSMERR_CSP_INVALID_KEY; 927 } 928 929 openKey->priv_key = cssmDataToBn(privKeyInt); 930 if(openKey->priv_key == NULL) { 931 return CSSMERR_CSP_INVALID_KEY; 932 } 933 return 0; 934 } 935 catch(...) { 936 return CSSMERR_CSP_INVALID_KEY; 937 } 938} 939 940static 941CSSM_RETURN DSAPrivateKeyEncodePKCS8( 942 SecNssCoder &coder, 943 DSA *openKey, 944 CssmOwnedData &encodedKey) 945{ 946 try { 947 /* First convert into a NSS_DSAPrivateKeyPKCS8 */ 948 NSS_DSAPrivateKeyPKCS8 nssPrivKey; 949 NSS_DSAAlgParams algParams; 950 memset(&nssPrivKey, 0, sizeof(nssPrivKey)); 951 memset(&algParams, 0, sizeof(algParams)); 952 nssPrivKey.dsaAlg.params = &algParams; 953 intToCssmData(openKey->version, nssPrivKey.version, coder); 954 dsaToNssAlgIdX509(openKey, nssPrivKey.dsaAlg, coder); 955 956 /* pre-encode, nssPrivKey.privateKey is the DER-encoding of 957 * an ASN integer... */ 958 CSSM_DATA privKeyInt; 959 bnToCssmData(openKey->priv_key, privKeyInt, coder); 960 961 /* DER encode the privateKey portion into arena pool memory 962 * into NSS_DSAPrivateKeyPKCS8.privateKey */ 963 coder.encodeItem(&privKeyInt, kSecAsn1UnsignedIntegerTemplate, 964 nssPrivKey.privateKey); 965 966 /* DER encode the whole thing */ 967 PRErrorCode perr; 968 perr = SecNssEncodeItemOdata(&nssPrivKey, 969 kSecAsn1DSAPrivateKeyPKCS8Template, encodedKey); 970 return 0; 971 } 972 catch(...) { 973 /* ? */ 974 return CSSMERR_CSP_MEMORY_ERROR; 975 } 976} 977 978/* 979 * DSA public key, X509/openssl format. 980 */ 981static CSSM_RETURN DSAPublicKeyDecodeX509( 982 SecNssCoder &coder, 983 DSA *openKey, 984 void *p, 985 size_t length) 986{ 987 NSS_DSAPublicKeyX509 nssPubKey; 988 PRErrorCode perr; 989 CSSM_RETURN crtn; 990 991 memset(&nssPubKey, 0, sizeof(nssPubKey)); 992 perr = coder.decode(p, length, kSecAsn1DSAPublicKeyX509Template, 993 &nssPubKey); 994 if(perr) { 995 logAsnErr("decode(DSAPublicKeyX509)", perr); 996 return CSSMERR_CSP_INVALID_KEY; 997 } 998 999 /* X509 style DSA-specific alg params */ 1000 NSS_DSAAlgorithmIdX509 &algId = nssPubKey.dsaAlg; 1001 crtn = nssAlgIdToDsaX509(algId, openKey); 1002 if(crtn) { 1003 return crtn; 1004 } 1005 1006 /* inside of nssPubKey.publicKey is the DER-encoding of a 1007 * ASN Integer; decoded length was in bits */ 1008 nssPubKey.publicKey.Length = (nssPubKey.publicKey.Length + 7) / 8; 1009 CSSM_DATA pubKeyBytes = {0, NULL}; 1010 perr = coder.decodeItem(nssPubKey.publicKey, 1011 kSecAsn1UnsignedIntegerTemplate, 1012 &pubKeyBytes); 1013 if(perr) { 1014 logAsnErr("decode(NSS_DSAPublicKeyX509.publicKey)", perr); 1015 return CSSMERR_CSP_INVALID_KEY; 1016 } 1017 openKey->pub_key = cssmDataToBn(pubKeyBytes); 1018 1019 if(openKey->pub_key == NULL) { 1020 return CSSMERR_CSP_INVALID_KEY; 1021 } 1022 return 0; 1023} 1024 1025static CSSM_RETURN DSAPublicKeyEncodeX509( 1026 SecNssCoder &coder, 1027 DSA *openKey, 1028 CssmOwnedData &encodedKey) 1029{ 1030 try { 1031 /* convert to NSS_DSAPublicKeyX509 */ 1032 NSS_DSAPublicKeyX509 nssPubKey; 1033 NSS_DSAAlgParams algParams; 1034 memset(&nssPubKey, 0, sizeof(nssPubKey)); 1035 memset(&algParams, 0, sizeof(algParams)); 1036 nssPubKey.dsaAlg.params = &algParams; 1037 dsaToNssAlgIdX509(openKey, nssPubKey.dsaAlg, coder); 1038 1039 /* 1040 * publicKey is the DER-encoding of a ASN INTEGER wrapped in 1041 * an AsnBits 1042 */ 1043 CSSM_DATA pubKeyRaw; 1044 PRErrorCode perr; 1045 bnToCssmData(openKey->pub_key, pubKeyRaw, coder); 1046 perr = coder.encodeItem(&pubKeyRaw, kSecAsn1UnsignedIntegerTemplate, 1047 nssPubKey.publicKey); 1048 if(perr) { 1049 logAsnErr("encodeItem(DSAPublicKeyX509.publicKey)", perr); 1050 return CSSMERR_CSP_MEMORY_ERROR; 1051 } 1052 nssPubKey.publicKey.Length *= 8; 1053 1054 /* DER encode */ 1055 SecNssEncodeItemOdata(&nssPubKey, kSecAsn1DSAPublicKeyX509Template, 1056 encodedKey); 1057 return CSSM_OK; 1058 } 1059 catch(...) { 1060 /* ? */ 1061 return CSSMERR_CSP_MEMORY_ERROR; 1062 } 1063} 1064 1065/* 1066 * Encode public key portion only for calculating key digest. 1067 * Note this works just fine on a partial DSA public key, i.e., 1068 * A DSA public key's digest-capable blob is the same whether or 1069 * not the DSA key has its DSA parameters p, q, and g. 1070 */ 1071static CSSM_RETURN DSAPublicKeyEncodeHashable( 1072 SecNssCoder &coder, 1073 DSA *openKey, 1074 CssmOwnedData &encodedKey) 1075{ 1076 try { 1077 /* 1078 * publicKey is the DER-encoding of an ASN integer 1079 */ 1080 CSSM_DATA pubKey; 1081 bnToCssmData(openKey->pub_key, pubKey, coder); 1082 PRErrorCode perr; 1083 1084 perr = SecNssEncodeItemOdata(&pubKey, kSecAsn1UnsignedIntegerTemplate, 1085 encodedKey); 1086 if(perr) { 1087 logAsnErr("encode(DSAPubHashable)", perr); 1088 return CSSMERR_CSP_MEMORY_ERROR; 1089 } 1090 return CSSM_OK; 1091 } 1092 catch(...) { 1093 /* ? */ 1094 return CSSMERR_CSP_MEMORY_ERROR; 1095 } 1096} 1097 1098/* 1099 * DSA private key, custom openssl format. 1100 */ 1101static CSSM_RETURN DSAPrivateKeyDecodeOpenssl( 1102 SecNssCoder &coder, 1103 DSA *openKey, 1104 void *p, 1105 size_t length) 1106{ 1107 NSS_DSAPrivateKeyOpenssl nssPrivKey; 1108 PRErrorCode perr; 1109 1110 memset(&nssPrivKey, 0, sizeof(nssPrivKey)); 1111 perr = coder.decode(p, length, kSecAsn1DSAPrivateKeyOpensslTemplate, 1112 &nssPrivKey); 1113 if(perr) { 1114 logAsnErr("decode(DSAPrivateKeyOpenssl)", perr); 1115 return CSSMERR_CSP_INVALID_KEY; 1116 } 1117 1118 /* convert nssPrivKey fields to RSA key fields */ 1119 try { 1120 openKey->version = cssmDataToInt(nssPrivKey.version); 1121 openKey->p = cssmDataToBn(nssPrivKey.p); 1122 openKey->q = cssmDataToBn(nssPrivKey.q); 1123 openKey->g = cssmDataToBn(nssPrivKey.g); 1124 openKey->pub_key = cssmDataToBn(nssPrivKey.pub); 1125 openKey->priv_key = cssmDataToBn(nssPrivKey.priv); 1126 } 1127 catch(...) { 1128 return CSSMERR_CSP_MEMORY_ERROR; 1129 } 1130 return 0; 1131} 1132 1133static CSSM_RETURN DSAPrivateKeyEncodeOpenssl( 1134 SecNssCoder &coder, 1135 DSA *openKey, 1136 CssmOwnedData &encodedKey) 1137{ 1138 NSS_DSAPrivateKeyOpenssl nssPrivKey; 1139 PRErrorCode perr; 1140 1141 /* convert to NSS_DSAPrivateKeyOpenssl */ 1142 try { 1143 intToCssmData(openKey->version, nssPrivKey.version, coder); 1144 bnToCssmData(openKey->p, nssPrivKey.p, coder); 1145 bnToCssmData(openKey->q, nssPrivKey.q, coder); 1146 bnToCssmData(openKey->g, nssPrivKey.g, coder); 1147 bnToCssmData(openKey->pub_key, nssPrivKey.pub, coder); 1148 bnToCssmData(openKey->priv_key, nssPrivKey.priv, coder); 1149 } 1150 catch(...) { 1151 /* ? */ 1152 return CSSMERR_CSP_MEMORY_ERROR; 1153 } 1154 1155 /* DER encode */ 1156 perr = SecNssEncodeItemOdata(&nssPrivKey, kSecAsn1DSAPrivateKeyOpensslTemplate, 1157 encodedKey); 1158 if(perr) { 1159 logAsnErr("encode(DSAPrivateKeyOpenssl)", perr); 1160 return CSSMERR_CSP_MEMORY_ERROR; 1161 } 1162 return CSSM_OK; 1163} 1164 1165CSSM_RETURN DSAPublicKeyDecode( 1166 DSA *openKey, 1167 CSSM_KEYBLOB_FORMAT format, 1168 void *p, 1169 size_t length) 1170{ 1171 SecNssCoder coder; 1172 1173 switch(format) { 1174 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: 1175 return DSAPublicKeyDecodeFIPS186(coder, openKey, p, length); 1176 case CSSM_KEYBLOB_RAW_FORMAT_X509: 1177 return DSAPublicKeyDecodeX509(coder, openKey, p, length); 1178 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: 1179 return DSAPublicKeyDecodeOpenSSH2(openKey, p, length); 1180 default: 1181 assert(0); 1182 return CSSMERR_CSP_INTERNAL_ERROR; 1183 } 1184} 1185 1186CSSM_RETURN DSAPublicKeyEncode( 1187 DSA *openKey, 1188 CSSM_KEYBLOB_FORMAT format, 1189 const CssmData &descData, 1190 CssmOwnedData &encodedKey) 1191{ 1192 SecNssCoder coder; 1193 1194 switch(format) { 1195 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: 1196 return DSAPublicKeyEncodeFIPS186(coder, openKey, encodedKey); 1197 case CSSM_KEYBLOB_RAW_FORMAT_X509: 1198 return DSAPublicKeyEncodeX509(coder, openKey, encodedKey); 1199 case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: 1200 return DSAPublicKeyEncodeHashable(coder, openKey, encodedKey); 1201 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: 1202 return DSAPublicKeyEncodeOpenSSH2(openKey, descData, encodedKey); 1203 default: 1204 assert(0); 1205 return CSSMERR_CSP_INTERNAL_ERROR; 1206 } 1207} 1208 1209CSSM_RETURN DSAPrivateKeyDecode( 1210 DSA *openKey, 1211 CSSM_KEYBLOB_FORMAT format, 1212 void *p, 1213 size_t length) 1214{ 1215 SecNssCoder coder; 1216 1217 switch(format) { 1218 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: 1219 return DSAPrivateKeyDecodeFIPS186(coder, openKey, p, (unsigned)length); 1220 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: 1221 return DSAPrivateKeyDecodeOpenssl(coder, openKey, p, length); 1222 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: 1223 return DSAPrivateKeyDecodePKCS8(coder, openKey, p, (unsigned)length); 1224 default: 1225 assert(0); 1226 return CSSMERR_CSP_INTERNAL_ERROR; 1227 } 1228} 1229 1230CSSM_RETURN DSAPrivateKeyEncode( 1231 DSA *openKey, 1232 CSSM_KEYBLOB_FORMAT format, 1233 const CssmData &descData, 1234 CssmOwnedData &encodedKey) 1235{ 1236 SecNssCoder coder; 1237 1238 switch(format) { 1239 case CSSM_KEYBLOB_RAW_FORMAT_FIPS186: 1240 return DSAPrivateKeyEncodeFIPS186(coder, openKey, encodedKey); 1241 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: 1242 return DSAPrivateKeyEncodeOpenssl(coder, openKey, encodedKey); 1243 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: 1244 return DSAPrivateKeyEncodePKCS8(coder, openKey, encodedKey); 1245 default: 1246 assert(0); 1247 return CSSMERR_CSP_INTERNAL_ERROR; 1248 } 1249} 1250 1251#pragma mark - 1252#pragma mark *** DSA Signature encode/decode *** 1253 1254CSSM_RETURN DSASigEncode( 1255 DSA_SIG *openSig, 1256 CssmOwnedData &encodedSig) 1257{ 1258 /* temp allocs from this pool */ 1259 SecNssCoder coder; 1260 /* convert to NSS_DSASignature */ 1261 NSS_DSASignature nssSig; 1262 1263 try { 1264 bnToCssmData(openSig->r, nssSig.r, coder); 1265 bnToCssmData(openSig->s, nssSig.s, coder); 1266 } 1267 catch(...) { 1268 /* ? */ 1269 return CSSMERR_CSP_MEMORY_ERROR; 1270 } 1271 1272 PRErrorCode prtn = SecNssEncodeItemOdata(&nssSig, 1273 kSecAsn1DSASignatureTemplate, encodedSig); 1274 if(prtn) { 1275 return CSSMERR_CSP_MEMORY_ERROR; 1276 } 1277 return CSSM_OK; 1278} 1279 1280CSSM_RETURN DSASigDecode( 1281 DSA_SIG *openSig, 1282 const void *p, 1283 unsigned length) 1284{ 1285 NSS_DSASignature nssSig; 1286 SecNssCoder coder; 1287 1288 memset(&nssSig, 0, sizeof(nssSig)); 1289 PRErrorCode perr = coder.decode(p, length, 1290 kSecAsn1DSASignatureTemplate, &nssSig); 1291 if(perr) { 1292 logAsnErr("decode(DSASigDecode)", perr); 1293 return CSSMERR_CSP_INVALID_SIGNATURE; 1294 } 1295 1296 try { 1297 openSig->r = cssmDataToBn(nssSig.r); 1298 openSig->s = cssmDataToBn(nssSig.s); 1299 } 1300 catch(...) { 1301 return CSSMERR_CSP_MEMORY_ERROR; 1302 } 1303 return 0; 1304} 1305 1306#pragma mark - 1307#pragma mark *** DSA Algorithm Parameters encode/decode *** 1308 1309CSSM_RETURN DSAEncodeAlgParams( 1310 NSS_DSAAlgParams &algParams, 1311 CssmOwnedData &encodedParams) 1312{ 1313 PRErrorCode prtn = SecNssEncodeItemOdata(&algParams, 1314 kSecAsn1DSAAlgParamsTemplate, encodedParams); 1315 if(prtn) { 1316 return CSSMERR_CSP_MEMORY_ERROR; 1317 } 1318 return CSSM_OK; 1319} 1320 1321CSSM_RETURN DSADecodeAlgParams( 1322 NSS_DSAAlgParams &algParams, 1323 const void *p, 1324 unsigned len, 1325 SecNssCoder &coder) 1326{ 1327 1328 memset(&algParams, 0, sizeof(algParams)); 1329 PRErrorCode perr = coder.decode(p, len, 1330 kSecAsn1DSAAlgParamsTemplate, &algParams); 1331 if(perr) { 1332 logAsnErr("decode(DSAAlgParams)", perr); 1333 return CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS; 1334 } 1335 return CSSM_OK; 1336} 1337 1338#pragma mark - 1339#pragma mark *** Diffie-Hellman key encode/decode *** 1340static 1341CSSM_RETURN DHPrivateKeyDecodePKCS3( 1342 SecNssCoder &coder, 1343 DH *openKey, 1344 unsigned char *p, 1345 unsigned length) 1346{ 1347 NSS_DHPrivateKey nssPrivKey; 1348 PRErrorCode perr; 1349 1350 memset(&nssPrivKey, 0, sizeof(nssPrivKey)); 1351 perr = coder.decode(p, length, kSecAsn1DHPrivateKeyTemplate, &nssPrivKey); 1352 if(perr) { 1353 logAsnErr("decode(DHPrivateKey)", perr); 1354 return CSSMERR_CSP_INVALID_KEY; 1355 } 1356 1357 /* verify alg identifier */ 1358 const CSSM_OID *oid = &nssPrivKey.dhOid; 1359 if(!cspCompareCssmData(oid, &CSSMOID_DH)) { 1360 sslAsn1Debug("DHPrivateKeyDecode: bad OID"); 1361 return CSSMERR_CSP_ALGID_MISMATCH; 1362 } 1363 1364 NSS_DHParameter ¶ms = nssPrivKey.params; 1365 1366 try { 1367 openKey->priv_key = cssmDataToBn(nssPrivKey.secretPart); 1368 openKey->p = cssmDataToBn(params.prime); 1369 openKey->g = cssmDataToBn(params.base); 1370 /* TBD - ignore privateValueLength for now */ 1371 } 1372 catch(...) { 1373 /* FIXME - bad sig? memory? */ 1374 return CSSMERR_CSP_MEMORY_ERROR; 1375 } 1376 return 0; 1377} 1378 1379static 1380CSSM_RETURN DHPrivateKeyEncodePKCS3( 1381 SecNssCoder &coder, 1382 DH *openKey, 1383 CssmOwnedData &encodedKey) 1384{ 1385 /* convert into a NSS_DHPrivateKey */ 1386 NSS_DHPrivateKey nssPrivKey; 1387 NSS_DHParameter ¶ms = nssPrivKey.params; 1388 memset(&nssPrivKey, 0, sizeof(nssPrivKey)); 1389 nssPrivKey.dhOid = CSSMOID_DH; 1390 1391 1392 try { 1393 bnToCssmData(openKey->priv_key, nssPrivKey.secretPart, coder); 1394 bnToCssmData(openKey->p, params.prime, coder); 1395 bnToCssmData(openKey->g, params.base, coder); 1396 if(openKey->length) { 1397 /* actually currently not supported in openssl... */ 1398 intToCssmData(openKey->length, params.privateValueLength, coder); 1399 } 1400 } 1401 catch(...) { 1402 return CSSMERR_CSP_MEMORY_ERROR; 1403 } 1404 1405 /* DER encode */ 1406 PRErrorCode perr; 1407 perr = SecNssEncodeItemOdata(&nssPrivKey, kSecAsn1DHPrivateKeyTemplate, 1408 encodedKey); 1409 if(perr) { 1410 logAsnErr("encode(DHPrivateKey)", perr); 1411 return CSSMERR_CSP_MEMORY_ERROR; 1412 } 1413 return CSSM_OK; 1414} 1415 1416/* 1417 * NSS_DHAlgorithmIdentifierX942 <--> DH 1418 * NOTE this is incomplete. It's functional on decode, but we throw 1419 * away everything except p and g. On encode, we put zeroes in 1420 * all the fields we don't deal with. Thus the encode side will NOT be 1421 * interoperable with other implementations. 1422 */ 1423static void dhToNssAlgIdX942( 1424 const DH *openKey, 1425 NSS_DHAlgorithmIdentifierX942 &algId, 1426 SecNssCoder &coder) 1427{ 1428 /* 1429 * When trying to encode a public key in X509 form, we may in 1430 * fact have nothing here - public keys created and exported in 1431 * PKCS3 have the pub_key value, and that's it. 1432 */ 1433 1434 memset(&algId, 0, sizeof(algId)); 1435 algId.oid = CSSMOID_ANSI_DH_PUB_NUMBER; // not mallocd 1436 NSS_DHDomainParamsX942 ¶ms = algId.params; 1437 uint8 zero = 0; 1438 CSSM_DATA czero = {1, &zero}; 1439 if(openKey->p != NULL) { 1440 bnToCssmData(openKey->p, params.p, coder); 1441 } 1442 else { 1443 coder.allocCopyItem(czero, params.p); 1444 } 1445 if(openKey->g != NULL) { 1446 bnToCssmData(openKey->g, params.g, coder); 1447 } 1448 else { 1449 coder.allocCopyItem(czero, params.g); 1450 } 1451 /* and we never have a vali0d q */ 1452 coder.allocCopyItem(czero, params.q); 1453 1454} 1455 1456static CSSM_RETURN nssAlgIdToDhX942( 1457 NSS_DHAlgorithmIdentifierX942 &algId, 1458 DH *openKey) 1459{ 1460 if(!cspCompareCssmData(&algId.oid, &CSSMOID_ANSI_DH_PUB_NUMBER)) { 1461 sslAsn1Debug("nssAlgIdToDhX942: bad OID"); 1462 return CSSMERR_CSP_INVALID_KEY; 1463 } 1464 openKey->p = cssmDataToBn(algId.params.p); 1465 openKey->g = cssmDataToBn(algId.params.g); 1466 return CSSM_OK; 1467} 1468 1469static 1470CSSM_RETURN DHPrivateKeyDecodePKCS8( 1471 SecNssCoder &coder, 1472 DH *openKey, 1473 unsigned char *p, 1474 unsigned length) 1475{ 1476 NSS_DHPrivateKeyPKCS8 nssPrivKey; 1477 PRErrorCode perr; 1478 1479 memset(&nssPrivKey, 0, sizeof(nssPrivKey)); 1480 perr = coder.decode(p, length, kSecAsn1DHPrivateKeyPKCS8Template, 1481 &nssPrivKey); 1482 if(perr) { 1483 logAsnErr("decode(DHPrivateKeyPKCS8)", perr); 1484 return CSSMERR_CSP_INVALID_KEY; 1485 } 1486 1487 try { 1488 CSSM_RETURN crtn = nssAlgIdToDhX942(nssPrivKey.algorithm, openKey); 1489 if(crtn) { 1490 return crtn; 1491 } 1492 1493 /* post-decode private key is a DER encoded integer */ 1494 CSSM_DATA privKeyInt = {0, NULL}; 1495 if(coder.decodeItem(nssPrivKey.privateKey, 1496 kSecAsn1UnsignedIntegerTemplate, 1497 &privKeyInt)) { 1498 logAsnErr("decode(DHPrivateKeyPKCS8 privKey int)", perr); 1499 return CSSMERR_CSP_INVALID_KEY; 1500 } 1501 1502 openKey->priv_key = cssmDataToBn(privKeyInt); 1503 } 1504 catch(...) { 1505 /* FIXME - bad sig? memory? */ 1506 return CSSMERR_CSP_MEMORY_ERROR; 1507 } 1508 return 0; 1509} 1510 1511static 1512CSSM_RETURN DHPrivateKeyEncodePKCS8( 1513 SecNssCoder &coder, 1514 DH *openKey, 1515 CssmOwnedData &encodedKey) 1516{ 1517 /* convert into a NSS_DHPrivateKeyPKCS8 */ 1518 NSS_DHPrivateKeyPKCS8 nssPrivKey; 1519 memset(&nssPrivKey, 0, sizeof(nssPrivKey)); 1520 uint8 vers = 0; 1521 nssPrivKey.version.Length = 1; 1522 nssPrivKey.version.Data = &vers; 1523 NSS_DHAlgorithmIdentifierX942 &alg = nssPrivKey.algorithm; 1524 1525 try { 1526 1527 dhToNssAlgIdX942(openKey, alg, coder); 1528 /* pre-encode, nssPrivKey.privateKey is the DER-encoding of 1529 * an ASN integer... */ 1530 CSSM_DATA privKeyInt; 1531 bnToCssmData(openKey->priv_key, privKeyInt, coder); 1532 1533 /* DER encode the privateKey portion into arena pool memory 1534 * into nssPrivKey.privateKey */ 1535 coder.encodeItem(&privKeyInt, kSecAsn1UnsignedIntegerTemplate, 1536 nssPrivKey.privateKey); 1537 } 1538 catch(...) { 1539 return CSSMERR_CSP_MEMORY_ERROR; 1540 } 1541 1542 /* DER encode */ 1543 PRErrorCode perr; 1544 perr = SecNssEncodeItemOdata(&nssPrivKey, kSecAsn1DHPrivateKeyPKCS8Template, 1545 encodedKey); 1546 if(perr) { 1547 logAsnErr("encode(DHPrivateKey)", perr); 1548 return CSSMERR_CSP_MEMORY_ERROR; 1549 } 1550 return CSSM_OK; 1551} 1552 1553/* 1554 * In the PKCS3 form, the public blob is simply the literal 1555 * public key value, not DER encoded. 1556 */ 1557static CSSM_RETURN DHPublicKeyDecodePKCS3( 1558 DH *openKey, 1559 SecNssCoder &coder, 1560 unsigned char *p, 1561 unsigned length) 1562{ 1563 try { 1564 CSSM_DATA pubKey = {(uint32)length, (uint8 *)p}; 1565 openKey->pub_key = cssmDataToBn(pubKey); 1566 return CSSM_OK; 1567 } 1568 catch(...) { 1569 return CSSMERR_CSP_MEMORY_ERROR; 1570 } 1571} 1572 1573static CSSM_RETURN DHPublicKeyEncodePKCS3( 1574 DH *openKey, 1575 SecNssCoder &coder, 1576 CssmOwnedData &encodedKey) 1577{ 1578 try { 1579 CSSM_DATA pubKey; 1580 bnToCssmData(openKey->pub_key, pubKey, coder); 1581 encodedKey.copy(CssmData::overlay(pubKey)); 1582 return CSSM_OK; 1583 } 1584 catch(...) { 1585 return CSSMERR_CSP_MEMORY_ERROR; 1586 } 1587} 1588 1589static CSSM_RETURN DHPublicKeyDecodeX509( 1590 DH *openKey, 1591 SecNssCoder &coder, 1592 unsigned char *p, 1593 unsigned length) 1594{ 1595 NSS_DHPublicKeyX509 nssPubKey; 1596 PRErrorCode perr; 1597 1598 memset(&nssPubKey, 0, sizeof(nssPubKey)); 1599 perr = coder.decode(p, length, kSecAsn1DHPublicKeyX509Template, 1600 &nssPubKey); 1601 if(perr) { 1602 logAsnErr("decode(DHPublicKeyX509)", perr); 1603 return CSSMERR_CSP_INVALID_KEY; 1604 } 1605 1606 try { 1607 CSSM_RETURN crtn = nssAlgIdToDhX942(nssPubKey.algorithm, openKey); 1608 if(crtn) { 1609 return crtn; 1610 } 1611 1612 /* 1613 * Post-decode public key length in bits 1614 * Contents are pub_key as DER-encoded INTEGER 1615 */ 1616 CSSM_DATA &pubKey = nssPubKey.publicKey; 1617 pubKey.Length = (pubKey.Length + 7) / 8; 1618 CSSM_DATA pubKeyInt = {0, NULL}; 1619 if(coder.decodeItem(pubKey, 1620 kSecAsn1UnsignedIntegerTemplate, &pubKeyInt)) { 1621 logAsnErr("decode(DHPublicKeyX509 pub key int)", perr); 1622 return CSSMERR_CSP_INVALID_KEY; 1623 } 1624 openKey->pub_key = cssmDataToBn(pubKeyInt); 1625 } 1626 catch(...) { 1627 /* FIXME - bad sig? memory? */ 1628 return CSSMERR_CSP_MEMORY_ERROR; 1629 } 1630 return 0; 1631} 1632 1633static CSSM_RETURN DHPublicKeyEncodeX509( 1634 DH *openKey, 1635 SecNssCoder &coder, 1636 CssmOwnedData &encodedKey) 1637{ 1638 /* convert into a NSS_DHPublicKeyX509 */ 1639 NSS_DHPublicKeyX509 nssPubKey; 1640 memset(&nssPubKey, 0, sizeof(nssPubKey)); 1641 NSS_DHAlgorithmIdentifierX942 &alg = nssPubKey.algorithm; 1642 1643 try { 1644 dhToNssAlgIdX942(openKey, alg, coder); 1645 1646 /* encode pub_key as integer */ 1647 CSSM_DATA pubKeyInt = {0, NULL}; 1648 bnToCssmData(openKey->pub_key, pubKeyInt, coder); 1649 coder.encodeItem(&pubKeyInt, kSecAsn1UnsignedIntegerTemplate, 1650 nssPubKey.publicKey); 1651 /* specify length in bits */ 1652 nssPubKey.publicKey.Length *= 8; 1653 } 1654 catch(...) { 1655 return CSSMERR_CSP_MEMORY_ERROR; 1656 } 1657 1658 /* DER encode */ 1659 PRErrorCode perr; 1660 perr = SecNssEncodeItemOdata(&nssPubKey, kSecAsn1DHPublicKeyX509Template, 1661 encodedKey); 1662 if(perr) { 1663 logAsnErr("encode(DHPublicKeyX509)", perr); 1664 return CSSMERR_CSP_MEMORY_ERROR; 1665 } 1666 return CSSM_OK; 1667} 1668 1669CSSM_RETURN DHPrivateKeyDecode( 1670 DH *openKey, 1671 CSSM_KEYBLOB_FORMAT format, 1672 unsigned char *p, 1673 unsigned length) 1674{ 1675 SecNssCoder coder; 1676 1677 switch(format) { 1678 case CSSM_KEYBLOB_RAW_FORMAT_PKCS3: 1679 return DHPrivateKeyDecodePKCS3(coder, openKey, p, length); 1680 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: 1681 return DHPrivateKeyDecodePKCS8(coder, openKey, p, length); 1682 default: 1683 assert(0); 1684 return CSSMERR_CSP_INTERNAL_ERROR; 1685 } 1686} 1687 1688CSSM_RETURN DHPrivateKeyEncode( 1689 DH *openKey, 1690 CSSM_KEYBLOB_FORMAT format, 1691 CssmOwnedData &encodedKey) 1692{ 1693 SecNssCoder coder; 1694 1695 switch(format) { 1696 case CSSM_KEYBLOB_RAW_FORMAT_PKCS3: 1697 return DHPrivateKeyEncodePKCS3(coder, openKey, encodedKey); 1698 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: 1699 return DHPrivateKeyEncodePKCS8(coder, openKey, encodedKey); 1700 default: 1701 assert(0); 1702 return CSSMERR_CSP_INTERNAL_ERROR; 1703 } 1704} 1705 1706CSSM_RETURN DHPublicKeyDecode( 1707 DH *openKey, 1708 CSSM_KEYBLOB_FORMAT format, 1709 unsigned char *p, 1710 unsigned length) 1711{ 1712 SecNssCoder coder; 1713 1714 switch(format) { 1715 case CSSM_KEYBLOB_RAW_FORMAT_PKCS3: 1716 return DHPublicKeyDecodePKCS3(openKey, coder, p, length); 1717 case CSSM_KEYBLOB_RAW_FORMAT_X509: 1718 return DHPublicKeyDecodeX509(openKey, coder, p, length); 1719 default: 1720 assert(0); 1721 return CSSMERR_CSP_INTERNAL_ERROR; 1722 } 1723} 1724 1725CSSM_RETURN DHPublicKeyEncode( 1726 DH *openKey, 1727 CSSM_KEYBLOB_FORMAT format, 1728 CssmOwnedData &encodedKey) 1729{ 1730 SecNssCoder coder; 1731 1732 switch(format) { 1733 case CSSM_KEYBLOB_RAW_FORMAT_PKCS3: 1734 return DHPublicKeyEncodePKCS3(openKey, coder, encodedKey); 1735 case CSSM_KEYBLOB_RAW_FORMAT_X509: 1736 return DHPublicKeyEncodeX509(openKey, coder, encodedKey); 1737 default: 1738 assert(0); 1739 return CSSMERR_CSP_INTERNAL_ERROR; 1740 } 1741} 1742 1743/* 1744 * Encode/decode a NSS_DHParameterBlock. 1745 */ 1746CSSM_RETURN DHParamBlockDecode( 1747 const CSSM_DATA &encParam, 1748 NSS_DHParameterBlock ¶mBlock, 1749 SecNssCoder &coder) 1750{ 1751 PRErrorCode perr; 1752 1753 memset(¶mBlock, 0, sizeof(paramBlock)); 1754 perr = coder.decodeItem(encParam, kSecAsn1DHParameterBlockTemplate, 1755 ¶mBlock); 1756 if(perr == 0) { 1757 return CSSM_OK; 1758 } 1759 1760 /* 1761 * CDSA Extension: the CDSA Algorithm Guide says that the D-H 1762 * parameter block is supposed to be wrapped with its accompanying 1763 * OID. However Openssl does not do this; it just exports 1764 * an encoded DHParameter rather than a DHParameterBlock. 1765 * For compatibility we'll try decoding the parameters as one 1766 * of these. 1767 */ 1768 memset(¶mBlock, 0, sizeof(paramBlock)); 1769 perr = coder.decodeItem(encParam, kSecAsn1DHParameterTemplate, 1770 ¶mBlock.params); 1771 if(perr == 0) { 1772 return CSSM_OK; 1773 } 1774 return CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS; 1775} 1776 1777#pragma mark - 1778#pragma mark *** Message Digest *** 1779 1780/* 1781 * Given a message digest and associated algorithm, cook up a PKCS1-style 1782 * DigestInfo and return its DER encoding. This is a necessary step for 1783 * RSA signature (both generating and verifying) - the output of this 1784 * routine is what gets encrypted during signing, and what is expected when 1785 * verifying (i.e., decrypting the signature). 1786 * 1787 * A good guess for the length of the output digestInfo is the size of the 1788 * key being used to sign/verify. The digest can never be larger than that. 1789 */ 1790CSSM_RETURN generateDigestInfo( 1791 const void *msgDigest, 1792 size_t digestLen, 1793 CSSM_ALGORITHMS digestAlg, // CSSM_ALGID_SHA1, etc. 1794 CssmOwnedData &encodedInfo, 1795 size_t maxEncodedSize) 1796{ 1797 if(digestAlg == CSSM_ALGID_NONE) { 1798 /* special case, no encode, just copy */ 1799 encodedInfo.copy(msgDigest, digestLen); 1800 return 0; 1801 } 1802 1803 NSS_DigestInfo digestInfo; 1804 CSSM_X509_ALGORITHM_IDENTIFIER &algId = digestInfo.digestAlgorithm; 1805 1806 memset(&digestInfo, 0, sizeof(digestInfo)); 1807 switch(digestAlg) { 1808 case CSSM_ALGID_MD5: 1809 algId.algorithm = CSSMOID_MD5; 1810 break; 1811 case CSSM_ALGID_MD2: 1812 algId.algorithm = CSSMOID_MD2; 1813 break; 1814 case CSSM_ALGID_SHA1: 1815 algId.algorithm = CSSMOID_SHA1; 1816 break; 1817 case CSSM_ALGID_SHA224: 1818 algId.algorithm = CSSMOID_SHA224; 1819 break; 1820 case CSSM_ALGID_SHA256: 1821 algId.algorithm = CSSMOID_SHA256; 1822 break; 1823 case CSSM_ALGID_SHA384: 1824 algId.algorithm = CSSMOID_SHA384; 1825 break; 1826 case CSSM_ALGID_SHA512: 1827 algId.algorithm = CSSMOID_SHA512; 1828 break; 1829 default: 1830 return CSSMERR_CSP_INVALID_ALGORITHM; 1831 } 1832 nullAlgParams(algId); 1833 digestInfo.digest.Data = (uint8 *)msgDigest; 1834 digestInfo.digest.Length = digestLen; 1835 1836 /* DER encode */ 1837 PRErrorCode perr; 1838 perr = SecNssEncodeItemOdata(&digestInfo, kSecAsn1DigestInfoTemplate, 1839 encodedInfo); 1840 if(perr) { 1841 logAsnErr("encode(digestInfo)", perr); 1842 return CSSMERR_CSP_MEMORY_ERROR; 1843 } 1844 return CSSM_OK; 1845} 1846 1847