1/* 2 * Copyright (c) 2003 Apple Computer, 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 * clNssUtils.cpp - support for libnssasn1-based ASN1 encode/decode 20 */ 21 22#include "clNssUtils.h" 23#include "clNameUtils.h" 24#include "CSPAttacher.h" 25#include <security_asn1/secasn1.h> 26#include <security_asn1/SecNssCoder.h> 27#include <security_asn1/nssUtils.h> 28#include <Security/keyTemplates.h> 29#include <Security/certExtensionTemplates.h> 30#include <Security/oidsalg.h> 31#include <Security/oidsattr.h> 32#include <Security/cssmapple.h> 33#include <string.h> 34 35#pragma mark ----- ArenaAllocator ----- 36 37/* 38 * Avoid inlining this for debuggability 39 */ 40void *ArenaAllocator::malloc(size_t len) throw(std::bad_alloc) 41{ 42 try { 43 return mCoder.malloc(len); 44 } 45 catch (...) { 46 throw std::bad_alloc(); 47 } 48} 49 50/* intentionally not implemented, should never be called */ 51void ArenaAllocator::free(void *p) throw() 52{ 53 throw std::bad_alloc(); 54} 55 56void *ArenaAllocator::realloc(void *p, size_t len) throw(std::bad_alloc) 57{ 58 throw std::bad_alloc(); 59} 60 61#pragma mark ----- Malloc/Copy/Compare CSSM_DATA ----- 62 63/* 64 * Misc. alloc/copy with arbitrary Allocator 65 */ 66/* malloc d.Data, set d.Length */ 67void clAllocData( 68 Allocator &alloc, 69 CSSM_DATA &dst, 70 size_t len) 71{ 72 if(len == 0) { 73 dst.Data = NULL; 74 } 75 else { 76 dst.Data = (uint8 *)alloc.malloc(len); 77 } 78 dst.Length = len; 79} 80 81/* malloc and copy */ 82void clAllocCopyData( 83 Allocator &alloc, 84 const CSSM_DATA &src, 85 CSSM_DATA &dst) 86{ 87 clAllocData(alloc, dst, src.Length); 88 if(dst.Length != 0) { 89 memmove(dst.Data, src.Data, src.Length); 90 } 91} 92 93/* 94 * Compare two CSSM_DATAs (or two CSSM_OIDs), return true if identical. 95 */ 96bool clCompareCssmData( 97 const CSSM_DATA *data1, 98 const CSSM_DATA *data2) 99{ 100 if((data1 == NULL) || (data1->Data == NULL) || 101 (data2 == NULL) || (data2->Data == NULL) || 102 (data1->Length != data2->Length)) { 103 return false; 104 } 105 if(data1->Length != data2->Length) { 106 return false; 107 } 108 if(memcmp(data1->Data, data2->Data, data1->Length) == 0) { 109 return true; 110 } 111 else { 112 return false; 113 } 114} 115 116#pragma mark ----- CSSM_DATA <--> uint32 ----- 117 118uint32 clDataToInt( 119 const CSSM_DATA &cdata, 120 CSSM_RETURN toThrow) /* = CSSMERR_CL_INVALID_CERT_POINTER */ 121{ 122 if((cdata.Length == 0) || (cdata.Data == NULL)) { 123 return 0; 124 } 125 size_t len = cdata.Length; 126 if(len > sizeof(uint32)) { 127 if(toThrow == 0) { 128 /* tolerate this */ 129 len = sizeof(uint32); 130 } 131 else { 132 CssmError::throwMe(toThrow); 133 } 134 } 135 136 uint32 rtn = 0; 137 uint8 *cp = cdata.Data; 138 for(size_t i=0; i<len; i++) { 139 rtn = (rtn << 8) | *cp++; 140 } 141 return rtn; 142} 143 144void clIntToData( 145 uint32 num, 146 CSSM_DATA &cdata, 147 Allocator &alloc) 148{ 149 uint32 len = 0; 150 151 if(num < 0x100) { 152 len = 1; 153 } 154 else if(num < 0x10000) { 155 len = 2; 156 } 157 else if(num < 0x1000000) { 158 len = 3; 159 } 160 else { 161 len = 4; 162 } 163 clAllocData(alloc, cdata, len); 164 uint8 *cp = &cdata.Data[len - 1]; 165 for(unsigned i=0; i<len; i++) { 166 *cp-- = num & 0xff; 167 num >>= 8; 168 } 169} 170 171#pragma mark ----- CSSM_BOOL <--> CSSM_DATA ----- 172/* 173 * A Bool is encoded as one byte of either 0 or 0xff 174 * Default of NSS boolean not present is false 175 */ 176CSSM_BOOL clNssBoolToCssm( 177 const CSSM_DATA &nssBool) 178{ 179 if((nssBool.Data != NULL) && (nssBool.Data[0] == 0xff)) { 180 return CSSM_TRUE; 181 } 182 else { 183 return CSSM_FALSE; 184 } 185} 186 187void clCssmBoolToNss( 188 CSSM_BOOL cBool, 189 CSSM_DATA &nssBool, 190 Allocator &alloc) 191{ 192 uint32 num = cBool ? 0xff : 0; 193 clIntToData(num, nssBool, alloc); 194} 195 196#pragma mark ----- Bit String manipulation ----- 197 198/* 199 * Adjust the length of a CSSM_DATA representing a pre-encoded 200 * bit string. On entry the length field is the number of bytes 201 * of data; en exit, the number if bits. Trailing zero bits 202 * are counted as unused (which is how KeyUsage and NetscapeCertType 203 * extensions are encoded). 204 */ 205void clCssmBitStringToNss( 206 CSSM_DATA &b) 207{ 208 size_t numBits = b.Length * 8; 209 210 /* start at end of bit array, scanning backwards looking 211 * for the first set bit */ 212 bool foundSet = false; 213 for(ptrdiff_t dex=b.Length-1; dex>=0; dex--) { 214 unsigned bitMask = 0x01; 215 uint8 byte = b.Data[dex]; 216 for(unsigned bdex=0; bdex<8; bdex++) { 217 if(byte & bitMask) { 218 foundSet = true; 219 break; 220 } 221 else { 222 bitMask <<= 1; 223 numBits--; 224 } 225 } 226 if(foundSet) { 227 break; 228 } 229 } 230 /* !foundSet --> numBits = 0 */ 231 assert(((numBits > 0) & foundSet) || ((numBits == 0) && !foundSet)); 232 b.Length = numBits; 233} 234 235/* 236 * On entry, Length is bit count; on exit, a byte count. 237 * The job here is to ensure that bits marked as "unused" in the 238 * BER encoding are cleared. Encoding rules say they are undefined in 239 * the actual encoding. 240 */ 241void clNssBitStringToCssm( 242 CSSM_DATA &b) 243{ 244 CSSM_SIZE byteCount = (b.Length + 7) / 8; 245 unsigned partialBits = b.Length & 0x7; 246 b.Length = byteCount; 247 if(partialBits == 0) { 248 return; 249 } 250 251 /* mask off unused bits */ 252 unsigned unusedBits = 8 - partialBits; 253 uint8 *bp = b.Data + b.Length - 1; 254 /* mask = (2 ** unusedBits) - 1 */ 255 unsigned mask = (1 << unusedBits) - 1; 256 *bp &= ~mask; 257} 258 259#pragma mark ----- NSS array manipulation ----- 260/* 261 * How many items in a NULL-terminated array of pointers? 262 */ 263unsigned clNssArraySize( 264 const void **array) 265{ 266 unsigned count = 0; 267 if (array) { 268 while (*array++) { 269 count++; 270 } 271 } 272 return count; 273} 274 275/* malloc a NULL-ed array of pointers of size num+1 */ 276void **clNssNullArray( 277 uint32 num, 278 SecNssCoder &coder) 279{ 280 unsigned len = (num + 1) * sizeof(void *); 281 void **p = (void **)coder.malloc(len); 282 memset(p, 0, len); 283 return p; 284} 285 286/* 287 * GIven a CSSM_DATA containing a decoded BIT_STRING, 288 * convert to a KeyUsage. 289 */ 290CE_KeyUsage clBitStringToKeyUsage( 291 const CSSM_DATA &cdata) 292{ 293 size_t toCopy = (cdata.Length + 7) / 8; 294 if(toCopy > 2) { 295 /* I hope I never see this... */ 296 clErrorLog("clBitStringToKeyUsage: KeyUsage larger than 2 bytes!"); 297 toCopy = 2; 298 } 299 unsigned char bits[2] = {0, 0}; 300 memmove(bits, cdata.Data, toCopy); 301 CE_KeyUsage usage = (((unsigned)bits[0]) << 8) | bits[1]; 302 return usage; 303} 304 305CSSM_ALGORITHMS CL_oidToAlg( 306 const CSSM_OID &oid) 307{ 308 CSSM_ALGORITHMS alg; 309 bool found = cssmOidToAlg(&oid, &alg); 310 if(!found) { 311 clErrorLog("CL_oidToAlg: unknown alg\n"); 312 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 313 } 314 return alg; 315} 316 317#pragma mark ----- copy CSSM_X509_ALGORITHM_IDENTIFIER ----- 318 319/* 320 * Copy CSSM_X509_ALGORITHM_IDENTIFIER, same format (NSS and CSSM). 321 */ 322void CL_copyAlgId( 323 const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId, 324 CSSM_X509_ALGORITHM_IDENTIFIER &dstAlgId, 325 Allocator &alloc) 326{ 327 clAllocCopyData(alloc, srcAlgId.algorithm, dstAlgId.algorithm); 328 clAllocCopyData(alloc, srcAlgId.parameters, dstAlgId.parameters); 329} 330 331void CL_freeCssmAlgId( 332 CSSM_X509_ALGORITHM_IDENTIFIER *cdsaObj, // optional 333 Allocator &alloc) 334{ 335 if(cdsaObj == NULL) { 336 return; 337 } 338 alloc.free(cdsaObj->algorithm.Data); 339 alloc.free(cdsaObj->parameters.Data); 340 memset(cdsaObj, 0, sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)); 341} 342 343 344#pragma mark ----- CSSM_X509_TIME <--> NSS format ----- 345 346/* 347 * Map the tag associated with a choice of DirectoryString elements to 348 * a template array for encoding/decoding that string type. 349 * Contrary to RFC2459, we allow the IA5String type, which is actually 350 * used in the real world (cf. the email address in Thawte's serverbasic 351 * cert). 352 */ 353 354/* The template chooser does the work here */ 355 356bool CL_nssTimeToCssm( 357 const NSS_TaggedItem &nssTime, 358 CSSM_X509_TIME &cssmObj, 359 Allocator &alloc) 360{ 361 cssmObj.timeType = nssTime.tag; 362 clAllocCopyData(alloc, nssTime.item, cssmObj.time); 363 return true; 364} 365 366/* 367 * CSSM time to NSS time. 368 */ 369void CL_cssmTimeToNss( 370 const CSSM_X509_TIME &cssmTime, 371 NSS_TaggedItem &nssTime, 372 SecNssCoder &coder) 373{ 374 nssTime.tag = cssmTime.timeType; 375 coder.allocCopyItem(cssmTime.time, nssTime.item); 376} 377 378void CL_freeCssmTime( 379 CSSM_X509_TIME *cssmTime, 380 Allocator &alloc) 381{ 382 if(cssmTime == NULL) { 383 return; 384 } 385 if(cssmTime->time.Data) { 386 alloc.free(cssmTime->time.Data); 387 } 388 memset(cssmTime, 0, sizeof(CSSM_X509_TIME)); 389} 390 391 392#pragma mark ----- CSSM_X509_SUBJECT_PUBLIC_KEY_INFO <--> CSSM_KEY ----- 393 394/* 395 * Copy a CSSM_X509_SUBJECT_PUBLIC_KEY_INFO. 396 * 397 * Same format (NSS and CSSM), EXCEPT: 398 * 399 * Objects which have just been NSS decoded or are about to be 400 * NSS encoded have the subjectPublicKey.Length field in BITS 401 * since this field is wrapped in a BIT STRING upon encoding. 402 * 403 * Caller tells us which format (bits or bytes) 404 * to use for each of {src, dst}. 405 */ 406void CL_copySubjPubKeyInfo( 407 const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &srcInfo, 408 bool srcInBits, 409 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &dstInfo, 410 bool dstInBits, 411 Allocator &alloc) 412{ 413 CL_copyAlgId(srcInfo.algorithm, dstInfo.algorithm, alloc); 414 415 CSSM_DATA srcKey = srcInfo.subjectPublicKey; 416 if(srcInBits) { 417 srcKey.Length = (srcKey.Length + 7) / 8; 418 } 419 clAllocCopyData(alloc, srcKey, dstInfo.subjectPublicKey); 420 if(dstInBits) { 421 dstInfo.subjectPublicKey.Length *= 8; 422 } 423} 424 425/* 426 * Obtain a CSSM_KEY from a CSSM_X509_SUBJECT_PUBLIC_KEY_INFO, 427 * inferring as much as we can from required fields 428 * (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO) and extensions (for 429 * KeyUse, obtained from the optional DecodedCert). 430 */ 431CSSM_KEY_PTR CL_extractCSSMKeyNSS( 432 const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &keyInfo, 433 Allocator &alloc, 434 const DecodedCert *decodedCert) // optional 435{ 436 CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR) alloc.malloc(sizeof(CSSM_KEY)); 437 memset(cssmKey, 0, sizeof(CSSM_KEY)); 438 CSSM_KEYHEADER &hdr = cssmKey->KeyHeader; 439 CssmRemoteData keyData(alloc, cssmKey->KeyData); 440 441 hdr.HeaderVersion = CSSM_KEYHEADER_VERSION; 442 /* CspId blank */ 443 hdr.BlobType = CSSM_KEYBLOB_RAW; 444 hdr.AlgorithmId = CL_oidToAlg(keyInfo.algorithm.algorithm); 445 hdr.KeyAttr = CSSM_KEYATTR_MODIFIABLE | CSSM_KEYATTR_EXTRACTABLE; 446 447 /* 448 * Format inferred from AlgorithmId. I have never seen these defined 449 * anywhere, e.g., what's the format of an RSA public key in a cert? 450 * X509 certainly doesn't say. However. the following two cases are 451 * known to be correct. 452 */ 453 switch(hdr.AlgorithmId) { 454 case CSSM_ALGID_RSA: 455 hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; 456 break; 457 case CSSM_ALGID_DSA: 458 case CSSM_ALGID_ECDSA: 459 case CSSM_ALGID_DH: 460 case CSSM_ALGMODE_PKCS1_EME_OAEP: 461 hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_X509; 462 break; 463 case CSSM_ALGID_FEE: 464 /* CSSM_KEYBLOB_RAW_FORMAT_NONE --> DER encoded */ 465 hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE; 466 break; 467 default: 468 /* punt */ 469 hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE; 470 } 471 hdr.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY; 472 473 /* KeyUsage inferred from extensions */ 474 if(decodedCert) { 475 hdr.KeyUsage = decodedCert->inferKeyUsage(); 476 } 477 else { 478 hdr.KeyUsage = CSSM_KEYUSE_ANY; 479 } 480 481 /* start/end date unknown, leave zero */ 482 hdr.WrapAlgorithmId = CSSM_ALGID_NONE; 483 hdr.WrapMode = CSSM_ALGMODE_NONE; 484 485 switch(hdr.AlgorithmId) { 486 case CSSM_ALGID_DSA: 487 case CSSM_ALGID_ECDSA: 488 case CSSM_ALGID_DH: 489 case CSSM_ALGMODE_PKCS1_EME_OAEP: 490 { 491 /* 492 * Just encode the whole subject public key info blob. 493 * NOTE we're assuming that the keyInfo.subjectPublicKey 494 * field is in the NSS_native BITSTRING format, i.e., 495 * its Length field is in bits and we don't have to adjust. 496 */ 497 PRErrorCode prtn = SecNssEncodeItemOdata(&keyInfo, 498 kSecAsn1SubjectPublicKeyInfoTemplate, keyData); 499 if(prtn) { 500 clErrorLog("extractCSSMKey: error on reencode\n"); 501 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); 502 } 503 break; 504 } 505 default: 506 /* 507 * RSA, FEE for now. 508 * keyInfo.subjectPublicKey (in BITS) ==> KeyData 509 */ 510 keyData.copy(keyInfo.subjectPublicKey.Data, 511 (keyInfo.subjectPublicKey.Length + 7) / 8); 512 } 513 514 /* 515 * LogicalKeySizeInBits - ask the CSP 516 */ 517 CSSM_CSP_HANDLE cspHand = getGlobalCspHand(true); 518 CSSM_KEY_SIZE keySize; 519 CSSM_RETURN crtn; 520 crtn = CSSM_QueryKeySizeInBits(cspHand, CSSM_INVALID_HANDLE, cssmKey, 521 &keySize); 522 switch(crtn) { 523 default: 524 CssmError::throwMe(crtn); 525 case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE: 526 /* 527 * This is how the CSP indicates a "partial" public key, 528 * with a valid public key value but no alg-specific 529 * parameters (currently, DSA only). 530 */ 531 hdr.KeyAttr |= CSSM_KEYATTR_PARTIAL; 532 /* and drop thru */ 533 case CSSM_OK: 534 cssmKey->KeyHeader.LogicalKeySizeInBits = 535 keySize.LogicalKeySizeInBits; 536 break; 537 } 538 539 keyData.release(); 540 return cssmKey; 541} 542 543/* 544 * Set up a encoded NULL for CSSM_X509_ALGORITHM_IDENTIFIER.parameters. 545 */ 546void CL_nullAlgParams( 547 CSSM_X509_ALGORITHM_IDENTIFIER &algId) 548{ 549 static const uint8 encNull[2] = { SEC_ASN1_NULL, 0 }; 550 CSSM_DATA encNullData; 551 encNullData.Data = (uint8 *)encNull; 552 encNullData.Length = 2; 553 554 algId.parameters = encNullData; 555} 556 557/* 558 * Convert a CSSM_KEY to a CSSM_X509_SUBJECT_PUBLIC_KEY_INFO. The 559 * CSSM key must be in raw format and with a specific blob format. 560 * -- RSA keys have to be CSSM_KEYBLOB_RAW_FORMAT_PKCS1 561 * -- DSA keys have to be CSSM_KEYBLOB_RAW_FORMAT_X509 562 * -- ECDSA keys have to be CSSM_KEYBLOB_RAW_FORMAT_X509 563 */ 564void CL_CSSMKeyToSubjPubKeyInfoNSS( 565 const CSSM_KEY &cssmKey, 566 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &nssKeyInfo, 567 SecNssCoder &coder) 568{ 569 const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader; 570 if(hdr.BlobType != CSSM_KEYBLOB_RAW) { 571 clErrorLog("CL SetField: must specify RAW key blob\n"); 572 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT); 573 } 574 memset(&nssKeyInfo, 0, sizeof(nssKeyInfo)); 575 576 /* algorithm and format dependent from here... */ 577 switch(hdr.AlgorithmId) { 578 case CSSM_ALGID_RSA: 579 if(hdr.Format != CSSM_KEYBLOB_RAW_FORMAT_PKCS1) { 580 clErrorLog("CL SetField: RSA key must be in PKCS1 format\n"); 581 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); 582 } 583 /* and fall thru */ 584 default: 585 { 586 /* Key header's algorithm --> OID */ 587 const CSSM_OID *oid = cssmAlgToOid(hdr.AlgorithmId); 588 if(oid == NULL) { 589 clErrorLog("CL SetField: Unknown key algorithm\n"); 590 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); 591 } 592 CSSM_X509_ALGORITHM_IDENTIFIER &algId = nssKeyInfo.algorithm; 593 coder.allocCopyItem(*oid, algId.algorithm); 594 595 /* NULL algorithm parameters, always in this case */ 596 CL_nullAlgParams(algId); 597 598 /* Copy key bits, destination is a BIT STRING */ 599 coder.allocCopyItem(cssmKey.KeyData, nssKeyInfo.subjectPublicKey); 600 nssKeyInfo.subjectPublicKey.Length *= 8; 601 break; 602 } 603 case CSSM_ALGID_DSA: 604 case CSSM_ALGID_ECDSA: 605 if(hdr.Format != CSSM_KEYBLOB_RAW_FORMAT_X509) { 606 clErrorLog("CL SetField: DSA/ECDSA key must be in X509 format\n"); 607 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); 608 } 609 610 /* 611 * All we do is decode the whole key blob into the 612 * SubjectPublicKeyInfo. 613 */ 614 if(coder.decodeItem(cssmKey.KeyData, 615 kSecAsn1SubjectPublicKeyInfoTemplate, 616 &nssKeyInfo)) { 617 clErrorLog("CL SetField: Error decoding DSA public key\n"); 618 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_FORMAT); 619 } 620 break; 621 } 622} 623 624void CL_freeCSSMKey( 625 CSSM_KEY_PTR cssmKey, 626 Allocator &alloc, 627 bool freeTop) 628{ 629 if(cssmKey == NULL) { 630 return; 631 } 632 alloc.free(cssmKey->KeyData.Data); 633 memset(cssmKey, 0, sizeof(CSSM_KEY)); 634 if(freeTop) { 635 alloc.free(cssmKey); 636 } 637} 638 639#pragma mark ----- CE_AuthorityKeyID <--> NSS_AuthorityKeyId ----- 640 641void CL_cssmAuthorityKeyIdToNss( 642 const CE_AuthorityKeyID &cdsaObj, 643 NSS_AuthorityKeyId &nssObj, 644 SecNssCoder &coder) 645{ 646 memset(&nssObj, 0, sizeof(nssObj)); 647 if(cdsaObj.keyIdentifierPresent) { 648 nssObj.keyIdentifier = (CSSM_DATA_PTR)coder.malloc(sizeof(CSSM_DATA)); 649 coder.allocCopyItem(cdsaObj.keyIdentifier, *nssObj.keyIdentifier); 650 } 651 if(cdsaObj.generalNamesPresent ) { 652 /* GeneralNames, the hard one */ 653 CL_cssmGeneralNamesToNss(*cdsaObj.generalNames, 654 nssObj.genNames, coder); 655 } 656 if(cdsaObj.serialNumberPresent) { 657 coder.allocCopyItem(cdsaObj.serialNumber,nssObj.serialNumber); 658 } 659} 660 661void CL_nssAuthorityKeyIdToCssm( 662 const NSS_AuthorityKeyId &nssObj, 663 CE_AuthorityKeyID &cdsaObj, 664 SecNssCoder &coder, // for temp decoding 665 Allocator &alloc) 666{ 667 if(nssObj.keyIdentifier != NULL) { 668 cdsaObj.keyIdentifierPresent = CSSM_TRUE; 669 clAllocCopyData(alloc, *nssObj.keyIdentifier, cdsaObj.keyIdentifier); 670 } 671 if(nssObj.genNames.names != NULL) { 672 /* GeneralNames, the hard one */ 673 cdsaObj.generalNamesPresent = CSSM_TRUE; 674 cdsaObj.generalNames = 675 (CE_GeneralNames *)alloc.malloc(sizeof(CE_GeneralNames)); 676 CL_nssGeneralNamesToCssm(nssObj.genNames, 677 *cdsaObj.generalNames, 678 coder, 679 alloc); 680 } 681 if(nssObj.serialNumber.Data != NULL) { 682 cdsaObj.serialNumberPresent = CSSM_TRUE; 683 clAllocCopyData(alloc, nssObj.serialNumber, cdsaObj.serialNumber); 684 } 685} 686 687#pragma mark ----- CE_AuthorityInfoAccess <--> NSS_AuthorityInfoAccess ----- 688 689void CL_cssmInfoAccessToNss( 690 const CE_AuthorityInfoAccess &cdsaObj, 691 NSS_AuthorityInfoAccess &nssObj, 692 SecNssCoder &coder) 693{ 694 memset(&nssObj, 0, sizeof(nssObj)); 695 uint32 numDescs = cdsaObj.numAccessDescriptions; 696 nssObj.accessDescriptions = (NSS_AccessDescription **)clNssNullArray(numDescs, coder); 697 698 for(unsigned dex=0; dex<numDescs; dex++) { 699 nssObj.accessDescriptions[dex] = coder.mallocn<NSS_AccessDescription>(); 700 CE_AccessDescription *src = &cdsaObj.accessDescriptions[dex]; 701 NSS_AccessDescription *dst = nssObj.accessDescriptions[dex]; 702 coder.allocCopyItem(src->accessMethod, dst->accessMethod); 703 704 /* Convert general name, then encode it into destination */ 705 NSS_GeneralName nssGenName; 706 CL_cssmGeneralNameToNss(src->accessLocation, nssGenName, coder); 707 PRErrorCode prtn = coder.encodeItem(&nssGenName, kSecAsn1GeneralNameTemplate, 708 dst->encodedAccessLocation); 709 if(prtn) { 710 clErrorLog("CL_cssmInfoAccessToNss: encode error\n"); 711 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); 712 } 713 } 714} 715 716void CL_infoAccessToCssm( 717 const NSS_AuthorityInfoAccess &nssObj, 718 CE_AuthorityInfoAccess &cdsaObj, 719 SecNssCoder &coder, // for temp decoding 720 Allocator &alloc) 721{ 722 memset(&cdsaObj, 0, sizeof(cdsaObj)); 723 unsigned numDescs = clNssArraySize((const void **)nssObj.accessDescriptions); 724 if(numDescs == 0) { 725 return; 726 } 727 cdsaObj.accessDescriptions = (CE_AccessDescription *)alloc.malloc( 728 numDescs * sizeof(CE_AccessDescription)); 729 cdsaObj.numAccessDescriptions = numDescs; 730 for(unsigned dex=0; dex<numDescs; dex++) { 731 CE_AccessDescription *dst = &cdsaObj.accessDescriptions[dex]; 732 NSS_AccessDescription *src = nssObj.accessDescriptions[dex]; 733 clAllocCopyData(alloc, src->accessMethod, dst->accessMethod); 734 735 /* decode the general name */ 736 NSS_GeneralName nssGenName; 737 memset(&nssGenName, 0, sizeof(nssGenName)); 738 PRErrorCode prtn = coder.decodeItem(src->encodedAccessLocation, 739 kSecAsn1GeneralNameTemplate, &nssGenName); 740 if(prtn) { 741 clErrorLog("***Error decoding NSS_AuthorityInfoAccess.accessLocation\n"); 742 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 743 } 744 745 /* then convert the result to CSSM */ 746 CL_nssGeneralNameToCssm(nssGenName, dst->accessLocation, coder, alloc); 747 } 748} 749 750void CL_freeInfoAccess( 751 CE_AuthorityInfoAccess &cssmInfo, 752 Allocator &alloc) 753{ 754 uint32 numDescs = cssmInfo.numAccessDescriptions; 755 for(unsigned dex=0; dex<numDescs; dex++) { 756 CE_AccessDescription *dst = &cssmInfo.accessDescriptions[dex]; 757 alloc.free(dst->accessMethod.Data); 758 CL_freeCssmGeneralName(dst->accessLocation, alloc); 759 } 760 alloc.free(cssmInfo.accessDescriptions); 761} 762 763 764#pragma mark ----- CE_QC_Statements <--> NSS_QC_Statements ----- 765 766void CL_cssmQualCertStatementsToNss( 767 const CE_QC_Statements &cdsaObj, 768 NSS_QC_Statements &nssObj, 769 SecNssCoder &coder) 770{ 771 memset(&nssObj, 0, sizeof(nssObj)); 772 uint32 numQcs = cdsaObj.numQCStatements; 773 nssObj.qcStatements = 774 (NSS_QC_Statement **)clNssNullArray(numQcs, coder); 775 for(uint32 dex=0; dex<numQcs; dex++) { 776 nssObj.qcStatements[dex] = (NSS_QC_Statement *) 777 coder.malloc(sizeof(NSS_QC_Statement)); 778 NSS_QC_Statement *dst = nssObj.qcStatements[dex]; 779 CE_QC_Statement *src = &cdsaObj.qcStatements[dex]; 780 memset(dst, 0, sizeof(*dst)); 781 coder.allocCopyItem(src->statementId, dst->statementId); 782 if(src->semanticsInfo) { 783 if(src->otherInfo) { 784 /* this is either/or, not both */ 785 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); 786 } 787 788 /* encode this CE_SemanticsInformation */ 789 CE_SemanticsInformation *srcSI = src->semanticsInfo; 790 NSS_SemanticsInformation dstSI; 791 memset(&dstSI, 0, sizeof(dstSI)); 792 if(srcSI->semanticsIdentifier) { 793 dstSI.semanticsIdentifier = (CSSM_DATA_PTR)coder.malloc(sizeof(CSSM_DATA)); 794 coder.allocCopyItem(*srcSI->semanticsIdentifier, 795 *dstSI.semanticsIdentifier); 796 } 797 if(srcSI->nameRegistrationAuthorities) { 798 dstSI.nameRegistrationAuthorities = 799 (NSS_GeneralNames *)coder.malloc(sizeof(NSS_GeneralNames)); 800 CL_cssmGeneralNamesToNss(*srcSI->nameRegistrationAuthorities, 801 *dstSI.nameRegistrationAuthorities, coder); 802 } 803 PRErrorCode prtn = coder.encodeItem(&dstSI, kSecAsn1SemanticsInformationTemplate, 804 dst->info); 805 if(prtn) { 806 clErrorLog("CL_cssmQualCertStatementsToNss: encode error\n"); 807 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); 808 } 809 810 } 811 if(src->otherInfo) { 812 /* drop in as ASN_ANY */ 813 coder.allocCopyItem(*src->otherInfo, dst->info); 814 } 815 } 816} 817 818void CL_qualCertStatementsToCssm( 819 const NSS_QC_Statements &nssObj, 820 CE_QC_Statements &cdsaObj, 821 SecNssCoder &coder, // for temp decoding 822 Allocator &alloc) 823{ 824 memset(&cdsaObj, 0, sizeof(cdsaObj)); 825 unsigned numQcs = clNssArraySize((const void **)nssObj.qcStatements); 826 if(numQcs == 0) { 827 return; 828 } 829 cdsaObj.qcStatements = (CE_QC_Statement *)alloc.malloc( 830 numQcs * sizeof(CE_AccessDescription)); 831 cdsaObj.numQCStatements = numQcs; 832 for(unsigned dex=0; dex<numQcs; dex++) { 833 CE_QC_Statement *dst = &cdsaObj.qcStatements[dex]; 834 NSS_QC_Statement *src = nssObj.qcStatements[dex]; 835 836 memset(dst, 0, sizeof(*dst)); 837 clAllocCopyData(alloc, src->statementId, dst->statementId); 838 839 /* 840 * Whether the optional info is a SemanticsInformation or is uninterpreted 841 * DER data depends on statementId. 842 */ 843 if(src->info.Data) { 844 if(clCompareCssmData(&src->statementId, &CSSMOID_OID_QCS_SYNTAX_V2)) { 845 NSS_SemanticsInformation srcSI; 846 memset(&srcSI, 0, sizeof(srcSI)); 847 848 /* decode info as a NSS_SemanticsInformation */ 849 PRErrorCode prtn = coder.decodeItem(src->info, 850 kSecAsn1SemanticsInformationTemplate, &srcSI); 851 if(prtn) { 852 clErrorLog("***Error decoding CE_SemanticsInformation\n"); 853 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 854 } 855 856 /* NSS_SemanticsInformation --> CE_SemanticsInformation */ 857 dst->semanticsInfo = 858 (CE_SemanticsInformation *)alloc.malloc(sizeof(CE_SemanticsInformation)); 859 CE_SemanticsInformation *dstSI = dst->semanticsInfo; 860 memset(dstSI, 0, sizeof(*dstSI)); 861 if(srcSI.semanticsIdentifier) { 862 dstSI->semanticsIdentifier = (CSSM_OID *)alloc.malloc(sizeof(CSSM_OID)); 863 clAllocCopyData(alloc, *srcSI.semanticsIdentifier, *dstSI->semanticsIdentifier); 864 } 865 if(srcSI.nameRegistrationAuthorities) { 866 dstSI->nameRegistrationAuthorities = 867 (CE_NameRegistrationAuthorities *)alloc.malloc( 868 sizeof(CE_NameRegistrationAuthorities)); 869 CL_nssGeneralNamesToCssm(*srcSI.nameRegistrationAuthorities, 870 *dstSI->nameRegistrationAuthorities, 871 coder, 872 alloc); 873 } 874 } 875 else { 876 dst->otherInfo = (CSSM_DATA_PTR)alloc.malloc(sizeof(CSSM_DATA)); 877 clAllocCopyData(alloc, src->info, *dst->otherInfo); 878 } 879 } 880 } 881} 882 883void CL_freeQualCertStatements( 884 CE_QC_Statements &cssmQCs, 885 Allocator &alloc) 886{ 887 uint32 numQCs = cssmQCs.numQCStatements; 888 for(unsigned dex=0; dex<numQCs; dex++) { 889 CE_QC_Statement *dst = &cssmQCs.qcStatements[dex]; 890 alloc.free(dst->statementId.Data); 891 if(dst->semanticsInfo) { 892 CE_SemanticsInformation *si = dst->semanticsInfo; 893 if(si->semanticsIdentifier) { 894 alloc.free(si->semanticsIdentifier->Data); 895 alloc.free(si->semanticsIdentifier); 896 } 897 if(si->nameRegistrationAuthorities) { 898 CL_freeCssmGeneralNames(si->nameRegistrationAuthorities, alloc); 899 alloc.free(si->nameRegistrationAuthorities); 900 } 901 alloc.free(si); 902 } 903 if(dst->otherInfo) { 904 alloc.free(dst->otherInfo->Data); 905 alloc.free(dst->otherInfo); 906 } 907 } 908 alloc.free(cssmQCs.qcStatements); 909} 910 911#pragma mark ----- decode/encode CE_DistributionPointName ----- 912 913/* This is always a DER-encoded blob at the NSS level */ 914void CL_decodeDistributionPointName( 915 const CSSM_DATA &nssBlob, 916 CE_DistributionPointName &cssmDpn, 917 SecNssCoder &coder, 918 Allocator &alloc) 919{ 920 memset(&cssmDpn, 0, sizeof(CE_DistributionPointName)); 921 if(nssBlob.Length == 0) { 922 clErrorLog("***CL_decodeDistributionPointName: bad PointName\n"); 923 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 924 } 925 unsigned char tag = nssBlob.Data[0] & SEC_ASN1_TAGNUM_MASK; 926 switch(tag) { 927 case NSS_DIST_POINT_FULL_NAME_TAG: 928 { 929 /* decode to temp coder memory */ 930 NSS_GeneralNames gnames; 931 gnames.names = NULL; 932 if(coder.decodeItem(nssBlob, kSecAsn1DistPointFullNameTemplate, 933 &gnames)) { 934 clErrorLog("***Error decoding DistPointFullName\n"); 935 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 936 } 937 938 cssmDpn.nameType = CE_CDNT_FullName; 939 cssmDpn.dpn.fullName = (CE_GeneralNames *)alloc.malloc( 940 sizeof(CE_GeneralNames)); 941 942 /* copy out to caller */ 943 CL_nssGeneralNamesToCssm(gnames, 944 *cssmDpn.dpn.fullName, coder, alloc); 945 break; 946 } 947 case NSS_DIST_POINT_RDN_TAG: 948 { 949 /* decode to temp coder memory */ 950 NSS_RDN rdn; 951 memset(&rdn, 0, sizeof(rdn)); 952 if(coder.decodeItem(nssBlob, kSecAsn1DistPointRDNTemplate, 953 &rdn)) { 954 clErrorLog("***Error decoding DistPointRDN\n"); 955 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 956 } 957 958 cssmDpn.nameType = CE_CDNT_NameRelativeToCrlIssuer; 959 cssmDpn.dpn.rdn = (CSSM_X509_RDN_PTR)alloc.malloc( 960 sizeof(CSSM_X509_RDN)); 961 962 /* copy out to caller */ 963 CL_nssRdnToCssm(rdn, *cssmDpn.dpn.rdn, alloc, coder); 964 break; 965 } 966 default: 967 clErrorLog("***Bad CE_DistributionPointName tag\n"); 968 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 969 } 970} 971 972void CL_encodeDistributionPointName( 973 CE_DistributionPointName &cpoint, 974 CSSM_DATA &npoint, 975 SecNssCoder &coder) 976{ 977 const SecAsn1Template *templ = NULL; 978 NSS_GeneralNames gnames; 979 NSS_RDN rdn; 980 void *encodeSrc = NULL; 981 982 /* 983 * Our job is to convert one of two incoming aggregate types 984 * into NSS format, then encode the result into npoint. 985 */ 986 switch(cpoint.nameType) { 987 case CE_CDNT_FullName: 988 CL_cssmGeneralNamesToNss(*cpoint.dpn.fullName, 989 gnames, coder); 990 encodeSrc = &gnames; 991 templ = kSecAsn1DistPointFullNameTemplate; 992 break; 993 994 case CE_CDNT_NameRelativeToCrlIssuer: 995 CL_cssmRdnToNss(*cpoint.dpn.rdn, rdn, coder); 996 encodeSrc = &rdn; 997 templ = kSecAsn1DistPointRDNTemplate; 998 break; 999 default: 1000 clErrorLog("CL_encodeDistributionPointName: bad nameType\n"); 1001 CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG); 1002 } 1003 if(coder.encodeItem(encodeSrc, templ, npoint)) { 1004 clErrorLog("CL_encodeDistributionPointName: encode error\n"); 1005 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); 1006 } 1007} 1008 1009 1010#pragma mark --- CE_CRLDistPointsSyntax <--> NSS_CRLDistributionPoints --- 1011 1012void CL_cssmDistPointsToNss( 1013 const CE_CRLDistPointsSyntax &cdsaObj, 1014 NSS_CRLDistributionPoints &nssObj, 1015 SecNssCoder &coder) 1016{ 1017 memset(&nssObj, 0, sizeof(nssObj)); 1018 unsigned numPoints = cdsaObj.numDistPoints; 1019 if(numPoints == 0) { 1020 return; 1021 } 1022 nssObj.distPoints = 1023 (NSS_DistributionPoint **)clNssNullArray(numPoints, coder); 1024 for(unsigned dex=0; dex<numPoints; dex++) { 1025 nssObj.distPoints[dex] = (NSS_DistributionPoint *) 1026 coder.malloc(sizeof(NSS_DistributionPoint)); 1027 NSS_DistributionPoint *npoint = nssObj.distPoints[dex]; 1028 memset(npoint, 0, sizeof(NSS_DistributionPoint)); 1029 CE_CRLDistributionPoint *cpoint = &cdsaObj.distPoints[dex]; 1030 1031 /* all fields are optional */ 1032 if(cpoint->distPointName) { 1033 /* encode and drop into ASN_ANY slot */ 1034 npoint->distPointName = (CSSM_DATA *) 1035 coder.malloc(sizeof(CSSM_DATA)); 1036 CL_encodeDistributionPointName(*cpoint->distPointName, 1037 *npoint->distPointName, coder); 1038 1039 } 1040 1041 if(cpoint->reasonsPresent) { 1042 /* bit string, presumed max length 8 bits */ 1043 coder.allocItem(npoint->reasons, 1); 1044 npoint->reasons.Data[0] = cpoint->reasons; 1045 /* adjust for bit string length */ 1046 npoint->reasons.Length = 8; 1047 } 1048 1049 if(cpoint->crlIssuer) { 1050 CL_cssmGeneralNamesToNss(*cpoint->crlIssuer, 1051 npoint->crlIssuer, coder); 1052 } 1053 } 1054} 1055 1056void CL_nssDistPointsToCssm( 1057 const NSS_CRLDistributionPoints &nssObj, 1058 CE_CRLDistPointsSyntax &cdsaObj, 1059 SecNssCoder &coder, // for temp decoding 1060 Allocator &alloc) 1061{ 1062 memset(&cdsaObj, 0, sizeof(cdsaObj)); 1063 unsigned numPoints = clNssArraySize((const void **)nssObj.distPoints); 1064 if(numPoints == 0) { 1065 return; 1066 } 1067 1068 unsigned len = sizeof(CE_CRLDistributionPoint) * numPoints; 1069 cdsaObj.distPoints = (CE_CRLDistributionPoint *)alloc.malloc(len); 1070 memset(cdsaObj.distPoints, 0, len); 1071 cdsaObj.numDistPoints = numPoints; 1072 1073 for(unsigned dex=0; dex<numPoints; dex++) { 1074 CE_CRLDistributionPoint &cpoint = cdsaObj.distPoints[dex]; 1075 NSS_DistributionPoint &npoint = *(nssObj.distPoints[dex]); 1076 1077 /* All three fields are optional */ 1078 if(npoint.distPointName != NULL) { 1079 /* Drop in a CE_DistributionPointName */ 1080 CE_DistributionPointName *cname = 1081 (CE_DistributionPointName *)alloc.malloc( 1082 sizeof(CE_DistributionPointName)); 1083 memset(cname, 0, sizeof(*cname)); 1084 cpoint.distPointName = cname; 1085 1086 /* 1087 * This one is currently still encoded; we have to peek 1088 * at its tag and decode accordingly. 1089 */ 1090 CL_decodeDistributionPointName(*npoint.distPointName, 1091 *cname, coder, alloc); 1092 } 1093 1094 if(npoint.reasons.Data != NULL) { 1095 /* careful, it's a bit string */ 1096 if(npoint.reasons.Length > 8) { 1097 clErrorLog("***CL_nssDistPointsToCssm: Malformed reasons\n"); 1098 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 1099 } 1100 cpoint.reasonsPresent = CSSM_TRUE; 1101 if(npoint.reasons.Length != 0) { 1102 cpoint.reasons = npoint.reasons.Data[0]; 1103 } 1104 } 1105 1106 if(npoint.crlIssuer.names != NULL) { 1107 /* Cook up a new CE_GeneralNames */ 1108 cpoint.crlIssuer = 1109 (CE_GeneralNames *)alloc.malloc(sizeof(CE_GeneralNames)); 1110 CL_nssGeneralNamesToCssm(npoint.crlIssuer, *cpoint.crlIssuer, 1111 coder, alloc); 1112 } 1113 } 1114} 1115 1116#pragma mark ----- IssuingDistributionPoint ----- 1117 1118void CL_nssIssuingDistPointToCssm( 1119 NSS_IssuingDistributionPoint *nssIdp, 1120 CE_IssuingDistributionPoint *cssmIdp, 1121 SecNssCoder &coder, 1122 Allocator &alloc) 1123{ 1124 /* All fields optional */ 1125 memset(cssmIdp, 0, sizeof(*cssmIdp)); 1126 if(nssIdp->distPointName) { 1127 CE_DistributionPointName *cssmDp = (CE_DistributionPointName *) 1128 alloc.malloc(sizeof(CE_DistributionPointName)); 1129 1130 /* 1131 * This one is currently still encoded; we have to peek 1132 * at its tag and decode accordingly. 1133 */ 1134 CL_decodeDistributionPointName(*nssIdp->distPointName, 1135 *cssmDp, coder, alloc); 1136 cssmIdp->distPointName = cssmDp; 1137 } 1138 if(nssIdp->onlyUserCerts) { 1139 cssmIdp->onlyUserCertsPresent = CSSM_TRUE; 1140 cssmIdp->onlyUserCerts = clNssBoolToCssm(*nssIdp->onlyUserCerts); 1141 } 1142 if(nssIdp->onlyCACerts) { 1143 cssmIdp->onlyCACertsPresent = CSSM_TRUE; 1144 cssmIdp->onlyCACerts = clNssBoolToCssm(*nssIdp->onlyCACerts); 1145 } 1146 if(nssIdp->onlySomeReasons) { 1147 cssmIdp->onlySomeReasonsPresent = CSSM_TRUE; 1148 if(nssIdp->onlySomeReasons->Length > 0) { 1149 cssmIdp->onlySomeReasons = *nssIdp->onlySomeReasons->Data; 1150 } 1151 else { 1152 cssmIdp->onlySomeReasons = 0; 1153 } 1154 } 1155 if(nssIdp->indirectCRL) { 1156 cssmIdp->indirectCrlPresent = CSSM_TRUE; 1157 cssmIdp->indirectCrl = clNssBoolToCssm(*nssIdp->indirectCRL); 1158 } 1159} 1160 1161#pragma mark --- CE_NameConstraints <--> NSS_NameConstraints --- 1162 1163void CL_cssmNameConstraintsToNss( 1164 const CE_NameConstraints &cdsaObj, 1165 NSS_NameConstraints &nssObj, 1166 SecNssCoder &coder) 1167{ 1168 //%%%FIXME tba 1169} 1170 1171void CL_nssNameConstraintsToCssm( 1172 const NSS_NameConstraints &nssObj, 1173 CE_NameConstraints &cdsaObj, 1174 SecNssCoder &coder, // for temp decoding 1175 Allocator &alloc) 1176{ 1177 //%%%FIXME tba 1178} 1179 1180void CL_freeCssmNameConstraints( 1181 CE_NameConstraints *cssmNcs, 1182 Allocator &alloc) 1183{ 1184 if(cssmNcs == NULL) { 1185 return; 1186 } 1187//%%%FIXME need to add a CL_freeCssmGeneralSubtrees function to clNameUtils{.h,.cpp} 1188#if 0 1189 switch(cssmDpn->nameType) { 1190 case CE_CDNT_FullName: 1191 CL_freeCssmGeneralNames(cssmDpn->dpn.fullName, alloc); 1192 alloc.free(cssmDpn->dpn.fullName); 1193 break; 1194 case CE_CDNT_NameRelativeToCrlIssuer: 1195 CL_freeX509Rdn(cssmDpn->dpn.rdn, alloc); 1196 alloc.free(cssmDpn->dpn.rdn); 1197 break; 1198 } 1199#endif 1200 memset(cssmNcs, 0, sizeof(*cssmNcs)); 1201} 1202 1203#pragma mark --- CE_PolicyMappings <--> NSS_PolicyMappings --- 1204 1205void CL_cssmPolicyMappingsToNss( 1206 const CE_PolicyMappings &cdsaObj, 1207 NSS_PolicyMappings &nssObj, 1208 SecNssCoder &coder) 1209{ 1210 //%%%FIXME tba 1211} 1212 1213void CL_nssPolicyMappingsToCssm( 1214 const NSS_PolicyMappings &nssObj, 1215 CE_PolicyMappings &cdsaObj, 1216 SecNssCoder &coder, // for temp decoding 1217 Allocator &alloc) 1218{ 1219 //%%%FIXME tba 1220} 1221 1222void CL_freeCssmPolicyMappings( 1223 CE_PolicyMappings *cssmPms, 1224 Allocator &alloc) 1225{ 1226 if(cssmPms == NULL) { 1227 return; 1228 } 1229 //%%%FIXME tba 1230 1231 memset(cssmPms, 0, sizeof(*cssmPms)); 1232} 1233 1234#pragma mark --- CE_PolicyConstraints <--> NSS_PolicyConstraints --- 1235 1236void CL_cssmPolicyConstraintsToNss( 1237 const CE_PolicyConstraints *cdsaObj, 1238 NSS_PolicyConstraints *nssObj, 1239 SecNssCoder &coder) 1240{ 1241 //%%%FIXME tba 1242} 1243 1244void CL_nssPolicyConstraintsToCssm( 1245 const NSS_PolicyConstraints *nssObj, 1246 CE_PolicyConstraints *cdsaObj, 1247 SecNssCoder &coder, // for temp decoding 1248 Allocator &alloc) 1249{ 1250 memset(cdsaObj, 0, sizeof(*cdsaObj)); 1251 if(nssObj->requireExplicitPolicy.Data) { 1252 cdsaObj->requireExplicitPolicyPresent = CSSM_TRUE; 1253 cdsaObj->inhibitPolicyMapping = clDataToInt( 1254 nssObj->requireExplicitPolicy, 0); 1255 } 1256 if(nssObj->inhibitPolicyMapping.Data) { 1257 cdsaObj->inhibitPolicyMappingPresent = CSSM_TRUE; 1258 cdsaObj->inhibitPolicyMapping = clDataToInt( 1259 nssObj->inhibitPolicyMapping, 0); 1260 } 1261} 1262 1263void CL_freeCssmPolicyConstraints( 1264 CE_PolicyConstraints *cssmPcs, 1265 Allocator &alloc) 1266{ 1267 if(cssmPcs == NULL) { 1268 return; 1269 } 1270 1271 memset(cssmPcs, 0, sizeof(*cssmPcs)); 1272} 1273 1274 1275#pragma mark ----- ECDSA_SigAlgParams support ----- 1276 1277/* 1278 * Some implementations use a two-OID mechanism to specify ECDSA signature 1279 * algorithm with a digest of other than SHA1. This is really not necessary; 1280 * we use the single-OID method (e.g. CSSMOID_ECDSA_WithSHA512) when 1281 * encoding, but we have to accomodate externally generated items with 1282 * the two-OID method. This routine decodes the digest OID and infers a 1283 * CSSM_ALGORITHMS from it. 1284 * Throws CSSMERR_CL_UNKNOWN_FORMAT on any error. 1285 */ 1286CSSM_ALGORITHMS CL_nssDecodeECDSASigAlgParams( 1287 const CSSM_DATA &encParams, 1288 SecNssCoder &coder) 1289{ 1290 CSSM_X509_ALGORITHM_IDENTIFIER algParams; 1291 memset(&algParams, 0, sizeof(algParams)); 1292 PRErrorCode prtn = coder.decodeItem(encParams, kSecAsn1AlgorithmIDTemplate, &algParams); 1293 if(prtn) { 1294 clErrorLog("CL_nssDecodeECDSASigAlgParams: error decoding CSSM_X509_ALGORITHM_IDENTIFIER\n"); 1295 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 1296 } 1297 1298 /* get the digest algorithm, convert to ECDSA w/digest OID */ 1299 CSSM_ALGORITHMS digestAlg = CL_oidToAlg(algParams.algorithm); 1300 switch(digestAlg) { 1301 case CSSM_ALGID_SHA1: 1302 return CSSM_ALGID_SHA1WithECDSA; 1303 case CSSM_ALGID_SHA224: 1304 return CSSM_ALGID_SHA224WithECDSA; 1305 case CSSM_ALGID_SHA256: 1306 return CSSM_ALGID_SHA256WithECDSA; 1307 case CSSM_ALGID_SHA384: 1308 return CSSM_ALGID_SHA384WithECDSA; 1309 case CSSM_ALGID_SHA512: 1310 return CSSM_ALGID_SHA512WithECDSA; 1311 default: 1312 clErrorLog("CL_nssDecodeECDSASigAlgParams: unknown digest algorithm\n"); 1313 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 1314 } 1315} 1316 1317#pragma mark ----- Top-level Cert/CRL encode and decode ----- 1318 1319/* 1320 * To ensure a secure means of signing and verifying TBSCert blobs, we 1321 * provide these functions to encode and decode just the top-level 1322 * elements of a certificate. Unfortunately there is no guarantee 1323 * that when you decode and re-encode a TBSCert blob, you get the 1324 * same thing you started with (although with DER rules, as opposed 1325 * to BER rules, you should). Thus when signing, we sign the TBSCert 1326 * and encode the signed cert here without ever decoding the TBSCert (or, 1327 * at least, without using the decoded version to get the encoded TBS blob). 1328 */ 1329 1330void CL_certCrlDecodeComponents( 1331 const CssmData &signedItem, // DER-encoded cert or CRL 1332 CssmOwnedData &tbsBlob, // still DER-encoded 1333 CssmOwnedData &algId, // ditto 1334 CssmOwnedData &rawSig) // raw bits (not an encoded AsnBits) 1335{ 1336 /* BER-decode into temp memory */ 1337 NSS_SignedCertOrCRL nssObj; 1338 SecNssCoder coder; 1339 PRErrorCode prtn; 1340 1341 memset(&nssObj, 0, sizeof(nssObj)); 1342 prtn = coder.decode(signedItem.data(), signedItem.length(), 1343 kSecAsn1SignedCertOrCRLTemplate, &nssObj); 1344 if(prtn) { 1345 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 1346 } 1347 1348 /* tbsBlob and algId are raw ASN_ANY including tags, which we pass 1349 * back to caller intact */ 1350 tbsBlob.copy(nssObj.tbsBlob.Data, nssObj.tbsBlob.Length); 1351 algId.copy(nssObj.signatureAlgorithm.Data, 1352 nssObj.signatureAlgorithm.Length); 1353 1354 /* signature is a bit string which we do in fact decode */ 1355 rawSig.copy(nssObj.signature.Data, 1356 (nssObj.signature.Length + 7) / 8); 1357} 1358 1359 1360/* 1361 * Given pre-DER-encoded blobs, do the final encode step for a signed cert. 1362 */ 1363void 1364CL_certEncodeComponents( 1365 const CssmData &TBSCert, // DER-encoded 1366 const CssmData &algId, // ditto 1367 const CssmData &rawSig, // raw bits, not encoded 1368 CssmOwnedData &signedCert) // DER-encoded 1369{ 1370 NSS_SignedCertOrCRL nssObj; 1371 nssObj.tbsBlob.Data = TBSCert.Data; 1372 nssObj.tbsBlob.Length = TBSCert.Length; 1373 nssObj.signatureAlgorithm.Data = algId.Data; 1374 nssObj.signatureAlgorithm.Length = algId.Length; 1375 nssObj.signature.Data = rawSig.Data; 1376 nssObj.signature.Length = rawSig.Length * 8; // BIT STRING 1377 1378 PRErrorCode prtn; 1379 1380 prtn = SecNssEncodeItemOdata(&nssObj, 1381 kSecAsn1SignedCertOrCRLTemplate,signedCert); 1382 if(prtn) { 1383 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); 1384 } 1385 1386} 1387