1/* 2 * Copyright (c) 2000-2001,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 * CertFields.cpp - convert between NSS-based Certificate components and CDSA-style 21 * fields. A major component of DecodedCert. 22 * 23 * Copyright (c) 2000,2011-2012,2014 Apple Inc. 24 */ 25 26#include "DecodedCert.h" 27#include "cldebugging.h" 28#include "CLCertExtensions.h" 29#include "clNssUtils.h" 30#include "clNameUtils.h" 31#include "CLFieldsCommon.h" 32#include <Security/oidscert.h> 33#include <Security/x509defs.h> 34#include <security_utilities/utilities.h> 35 36/*** 37 *** Version 38 *** Format = DER-encoded int (max of four bytes in this case) 39 ***/ 40static bool getField_Version ( 41 DecodedItem &item, 42 unsigned index, // which occurrence (0 = first) 43 uint32 &numFields, // RETURNED 44 CssmOwnedData &fieldValue) // RETURNED 45{ 46 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 47 const CSSM_DATA &vers = cert.mCert.tbs.version; 48 if(!tbsGetCheck(vers.Data, index)) { 49 /* not present, optional */ 50 return false; 51 } 52 fieldValue.copy(vers.Data, vers.Length); 53 numFields = 1; 54 return true; 55} 56 57static void setField_Version ( 58 DecodedItem &item, 59 const CssmData &fieldValue) 60{ 61 DecodedCert &cert = dynamic_cast<DecodedCert &>(item); 62 CSSM_DATA &vers = cert.mCert.tbs.version; 63 tbsSetCheck(vers.Data, fieldValue, 0, "version"); 64 cert.coder().allocCopyItem(fieldValue, vers); 65} 66 67 68#if this_is_a_template 69/*** 70 *** Version 71 *** Format = DER-encoded int (always four bytes in this case) 72 ***/ 73static bool getField_Version ( 74 DecodedItem &item, 75 unsigned index, // which occurrence (0 = first) 76 uint32 &numFields, // RETURNED 77 CssmOwnedData &fieldValue) // RETURNED 78{ 79 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 80 tbsGetCheck(cert.certificateToSign->version, index); 81} 82static void setField_Version ( 83 DecodedItem &item, 84 const CssmData &fieldValue) 85{ 86 DecodedCert &cert = dynamic_cast<DecodedCert &>(item); 87 tbsSetCheck(cert.certificateToSign->version, fieldValue, sizeof(uint32), 88 "version"); 89 90} 91static void freeField_Version ( 92 CssmOwnedData &fieldValue) 93{ 94} 95#endif 96 97/*** 98 *** Serial Number 99 *** Format = DER-encoded int, variable length 100 ***/ 101static bool getField_SerialNumber ( 102 DecodedItem &item, 103 unsigned index, // which occurrence (0 = first) 104 uint32 &numFields, // RETURNED 105 CssmOwnedData &fieldValue) // RETURNED 106{ 107 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 108 const CSSM_DATA &sn = cert.mCert.tbs.serialNumber; 109 if(!tbsGetCheck(sn.Data, index)) { 110 return false; 111 } 112 fieldValue.copy(sn.Data, sn.Length); 113 numFields = 1; 114 return true; 115} 116 117static void setField_SerialNumber ( 118 DecodedItem &item, 119 const CssmData &fieldValue) 120{ 121 DecodedCert &cert = dynamic_cast<DecodedCert &>(item); 122 CSSM_DATA &sn = cert.mCert.tbs.serialNumber; 123 tbsSetCheck(sn.Data, fieldValue, 0, "SerialNumber"); 124 cert.coder().allocCopyItem(fieldValue, sn); 125} 126 127/*** issuer/subject 128 *** Format = CSSM_X509_NAME 129 *** class Name from sm_x501if 130 ***/ 131static bool getField_Issuer ( 132 DecodedItem &item, 133 unsigned index, // which occurrence (0 = first) 134 uint32 &numFields, // RETURNED 135 CssmOwnedData &fieldValue) // RETURNED 136{ 137 if(index != 0) { 138 return false; 139 } 140 141 bool brtn; 142 143 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 144 try { 145 brtn = getField_RDN_NSS(cert.mCert.tbs.issuer, fieldValue); 146 if(brtn) { 147 numFields = 1; 148 } 149 } 150 catch (...) { 151 freeField_RDN(fieldValue); 152 throw; 153 } 154 return brtn; 155} 156 157static void setField_Issuer ( 158 DecodedItem &item, 159 const CssmData &fieldValue) 160{ 161 DecodedCert &cert = dynamic_cast<DecodedCert &>(item); 162 const CSSM_X509_NAME *cssmName = (const CSSM_X509_NAME *)fieldValue.Data; 163 NSS_Name &nssName = cert.mCert.tbs.issuer; 164 tbsSetCheck(nssName.rdns, fieldValue, sizeof(CSSM_X509_NAME), 165 "IssuerName"); 166 CL_cssmNameToNss(*cssmName, nssName, cert.coder()); 167} 168 169/*** subject ***/ 170static bool getField_Subject ( 171 DecodedItem &item, 172 unsigned index, // which occurrence (0 = first) 173 uint32 &numFields, // RETURNED 174 CssmOwnedData &fieldValue) // RETURNED 175{ 176 if(index != 0) { 177 return false; 178 } 179 180 bool brtn; 181 182 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 183 try { 184 brtn = getField_RDN_NSS(cert.mCert.tbs.subject, fieldValue); 185 if(brtn) { 186 numFields = 1; 187 } 188 } 189 catch (...) { 190 freeField_RDN(fieldValue); 191 throw; 192 } 193 return brtn; 194} 195 196static void setField_Subject ( 197 DecodedItem &item, 198 const CssmData &fieldValue) 199{ 200 DecodedCert &cert = dynamic_cast<DecodedCert &>(item); 201 const CSSM_X509_NAME *cssmName = (const CSSM_X509_NAME *)fieldValue.Data; 202 NSS_Name &nssName = cert.mCert.tbs.subject; 203 tbsSetCheck(nssName.rdns, fieldValue, sizeof(CSSM_X509_NAME), 204 "SubjectName"); 205 CL_cssmNameToNss(*cssmName, nssName, cert.coder()); 206} 207 208/*** 209 *** Issuer Name, Subject Name (normalized and encoded version) 210 *** Format = CSSM_DATA containing the DER encoding of the normalized name 211 ***/ 212static bool getFieldSubjectNorm( 213 DecodedItem &item, 214 unsigned index, // which occurrence (0 = first) 215 uint32 &numFields, // RETURNED 216 CssmOwnedData &fieldValue) // RETURNED 217{ 218 if(index != 0) { 219 return false; 220 } 221 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 222 return getField_normRDN_NSS(cert.mCert.tbs.derSubject, numFields, 223 fieldValue); 224} 225 226static bool getFieldIssuerNorm( 227 DecodedItem &item, 228 unsigned index, // which occurrence (0 = first) 229 uint32 &numFields, // RETURNED 230 CssmOwnedData &fieldValue) // RETURNED 231{ 232 if(index != 0) { 233 return false; 234 } 235 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 236 return getField_normRDN_NSS(cert.mCert.tbs.derIssuer, numFields, fieldValue); 237} 238 239/*** 240 *** Issuer Name, Subject Name (encoded, NON-normalized version) 241 *** Format = CSSM_DATA containing the DER encoding of the name 242 ***/ 243static bool getFieldSubjectStd( 244 DecodedItem &item, 245 unsigned index, // which occurrence (0 = first) 246 uint32 &numFields, // RETURNED 247 CssmOwnedData &fieldValue) // RETURNED 248{ 249 if(index != 0) { 250 return false; 251 } 252 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 253 fieldValue.copy(cert.mCert.tbs.derSubject); 254 numFields = 1; 255 return true; 256} 257 258static bool getFieldIssuerStd( 259 DecodedItem &item, 260 unsigned index, // which occurrence (0 = first) 261 uint32 &numFields, // RETURNED 262 CssmOwnedData &fieldValue) // RETURNED 263{ 264 if(index != 0) { 265 return false; 266 } 267 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 268 fieldValue.copy(cert.mCert.tbs.derIssuer); 269 numFields = 1; 270 return true; 271} 272 273/*** 274 *** TBS AlgId, Signature AlgId 275 *** Format = CSSM_X509_ALGORITHM_IDENTIFIER 276 ***/ 277/* TBS AlgId */ 278static bool getField_TbsAlgId ( 279 DecodedItem &item, 280 unsigned index, // which occurrence (0 = first) 281 uint32 &numFields, // RETURNED 282 CssmOwnedData &fieldValue) // RETURNED 283{ 284 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 285 const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId = cert.mCert.tbs.signature; 286 if(!tbsGetCheck(srcAlgId.algorithm.Data, index)) { 287 return false; 288 } 289 getField_AlgIdNSS(srcAlgId, fieldValue); 290 numFields = 1; 291 return true; 292} 293 294static void setField_TbsAlgId ( 295 DecodedItem &item, 296 const CssmData &fieldValue) 297{ 298 DecodedCert &cert = dynamic_cast<DecodedCert &>(item); 299 CSSM_X509_ALGORITHM_IDENTIFIER &dstAlgId = cert.mCert.tbs.signature; 300 tbsSetCheck(dstAlgId.algorithm.Data, fieldValue, 301 sizeof(CSSM_X509_ALGORITHM_IDENTIFIER), "TBS_AlgId"); 302 setField_AlgIdNSS(fieldValue, dstAlgId, cert.coder()); 303} 304 305/* Cert AlgId - read only */ 306static bool getField_CertAlgId ( 307 DecodedItem &item, 308 unsigned index, // which occurrence (0 = first) 309 uint32 &numFields, // RETURNED 310 CssmOwnedData &fieldValue) // RETURNED 311{ 312 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 313 const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId = cert.mCert.signatureAlgorithm; 314 if(!tbsGetCheck(srcAlgId.algorithm.Data, index)) { 315 return false; 316 } 317 getField_AlgIdNSS(srcAlgId, fieldValue); 318 numFields = 1; 319 return true; 320} 321 322/*** 323 *** Validity not before, not after 324 *** Format: CSSM_X509_TIME 325 ***/ 326 327/*** not before ***/ 328static bool getField_NotBefore ( 329 DecodedItem &item, 330 unsigned index, // which occurrence (0 = first) 331 uint32 &numFields, // RETURNED 332 CssmOwnedData &fieldValue) // RETURNED 333{ 334 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 335 const NSS_Time &srcTime = cert.mCert.tbs.validity.notBefore; 336 return getField_TimeNSS(srcTime, index, numFields, fieldValue); 337} 338 339static void setField_NotBefore ( 340 DecodedItem &item, 341 const CssmData &fieldValue) 342{ 343 DecodedCert &cert = dynamic_cast<DecodedCert &>(item); 344 NSS_Time &dstTime = cert.mCert.tbs.validity.notBefore; 345 tbsSetCheck(dstTime.item.Data, fieldValue, 346 sizeof(CSSM_X509_TIME), "NotBefore"); 347 setField_TimeNSS(fieldValue, dstTime, cert.coder()); 348} 349 350/*** not after ***/ 351static bool getField_NotAfter ( 352 DecodedItem &item, 353 unsigned index, // which occurrence (0 = first) 354 uint32 &numFields, // RETURNED 355 CssmOwnedData &fieldValue) // RETURNED 356{ 357 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 358 const NSS_Time &srcTime = cert.mCert.tbs.validity.notAfter; 359 return getField_TimeNSS(srcTime, index, numFields, fieldValue); 360} 361 362static void setField_NotAfter ( 363 DecodedItem &item, 364 const CssmData &fieldValue) 365{ 366 DecodedCert &cert = dynamic_cast<DecodedCert &>(item); 367 NSS_Time &dstTime = cert.mCert.tbs.validity.notAfter; 368 tbsSetCheck(dstTime.item.Data, fieldValue, 369 sizeof(CSSM_X509_TIME), "NotAfter"); 370 setField_TimeNSS(fieldValue, dstTime, cert.coder()); 371} 372 373/*** 374 *** Subject/issuer unique ID 375 *** Format: Raw bytes. It's stored in the cert as an ASN bit string; the decoded 376 *** bytes are present at this level (i.e., not tag and length in the bytes). 377 *** NOTE: this is not quite accurate in that we only provide byte-aligned size, 378 *** not bit-aligned. This field is rarely if ever used so I think it's O, but 379 *** beware. 380 ***/ 381static bool getField_SubjectUniqueId ( 382 DecodedItem &item, 383 unsigned index, // which occurrence (0 = first) 384 uint32 &numFields, // RETURNED 385 CssmOwnedData &fieldValue) // RETURNED 386{ 387 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 388 const CSSM_DATA &srcBits = cert.mCert.tbs.subjectID; 389 if(!tbsGetCheck(srcBits.Data, index)) { 390 return false; 391 } 392 393 /* That CSSM_DATA is a decoded BITSTRING; its length is in bits */ 394 CSSM_DATA tmp = srcBits; 395 tmp.Length = (tmp.Length + 7) / 8; 396 fieldValue.copy(tmp.Data, tmp.Length); 397 numFields = 1; 398 return true; 399} 400 401static void setField_SubjectUniqueId ( 402 DecodedItem &item, 403 const CssmData &fieldValue) 404{ 405 DecodedCert &cert = dynamic_cast<DecodedCert &>(item); 406 CSSM_DATA &dstBits = cert.mCert.tbs.subjectID; 407 tbsSetCheck(dstBits.Data, fieldValue, 0, "SubjectUniqueID"); 408 cert.coder().allocCopyItem(fieldValue, dstBits); 409 dstBits.Length *= 8; 410} 411 412static bool getField_IssuerUniqueId ( 413 DecodedItem &item, 414 unsigned index, // which occurrence (0 = first) 415 uint32 &numFields, // RETURNED 416 CssmOwnedData &fieldValue) // RETURNED 417{ 418 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 419 const CSSM_DATA &srcBits = cert.mCert.tbs.issuerID; 420 if(!tbsGetCheck(srcBits.Data, index)) { 421 return false; 422 } 423 424 /* That CSSM_DATA is a decoded BITSTRING; its length is in bits */ 425 CSSM_DATA tmp = srcBits; 426 tmp.Length = (tmp.Length + 7) / 8; 427 fieldValue.copy(tmp.Data, tmp.Length); 428 numFields = 1; 429 return true; 430} 431 432static void setField_IssuerUniqueId ( 433 DecodedItem &item, 434 const CssmData &fieldValue) 435{ 436 DecodedCert &cert = dynamic_cast<DecodedCert &>(item); 437 CSSM_DATA &dstBits = cert.mCert.tbs.issuerID; 438 tbsSetCheck(dstBits.Data, fieldValue, 0, "IssuerUniqueID"); 439 cert.coder().allocCopyItem(fieldValue, dstBits); 440 dstBits.Length *= 8; 441} 442 443/*** 444 *** Public key info 445 *** Format = CSSM_X509_SUBJECT_PUBLIC_KEY_INFO 446 ***/ 447static bool getField_PublicKeyInfo ( 448 DecodedItem &item, 449 unsigned index, // which occurrence (0 = first) 450 uint32 &numFields, // RETURNED 451 CssmOwnedData &fieldValue) // RETURNED 452{ 453 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 454 const CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &srcInfo = 455 cert.mCert.tbs.subjectPublicKeyInfo; 456 if(!tbsGetCheck(srcInfo.subjectPublicKey.Data, index)) { 457 return false; 458 } 459 460 Allocator &alloc = fieldValue.allocator; 461 fieldValue.malloc(sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO)); 462 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *dstInfo = 463 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)fieldValue.data(); 464 465 CL_copySubjPubKeyInfo(srcInfo, true, // length in bits here 466 *dstInfo, false, // length in bytes 467 alloc); 468 469 numFields = 1; 470 return true; 471} 472 473static void setField_PublicKeyInfo ( 474 DecodedItem &item, 475 const CssmData &fieldValue) 476{ 477 DecodedCert &cert = dynamic_cast<DecodedCert &>(item); 478 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &dstKeyInfo = 479 cert.mCert.tbs.subjectPublicKeyInfo; 480 tbsSetCheck(dstKeyInfo.subjectPublicKey.Data, fieldValue, 481 sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO), "PubKeyInfo"); 482 483 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *srcKeyInfo = 484 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)fieldValue.Data; 485 if((srcKeyInfo->subjectPublicKey.Data == NULL) || 486 (srcKeyInfo->subjectPublicKey.Length == 0)) { 487 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); 488 } 489 490 ArenaAllocator arenaAlloc(cert.coder()); 491 CL_copySubjPubKeyInfo(*srcKeyInfo, false, // length in bytes here 492 dstKeyInfo, true, // length in bits 493 arenaAlloc); 494} 495 496static void freeField_PublicKeyInfo ( 497 CssmOwnedData &fieldValue) 498{ 499 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *cssmKeyInfo = 500 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)fieldValue.data(); 501 if(cssmKeyInfo == NULL) { 502 return; 503 } 504 Allocator &alloc = fieldValue.allocator; 505 CL_freeCssmAlgId(&cssmKeyInfo->algorithm, alloc); 506 alloc.free(cssmKeyInfo->subjectPublicKey.Data); 507 memset(cssmKeyInfo, 0, sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO));} 508 509/*** 510 *** key info from CSSM_KEY 511 *** Format = CSSM_KEY 512 ***/ 513static bool getField_PublicKeyStruct ( 514 DecodedItem &item, 515 unsigned index, // which occurrence (0 = first) 516 uint32 &numFields, // RETURNED 517 CssmOwnedData &fieldValue) // RETURNED 518{ 519 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 520 if(!tbsGetCheck(cert.mCert.tbs.subjectPublicKeyInfo.subjectPublicKey.Data, 521 index)) { 522 return false; 523 } 524 CSSM_KEY_PTR cssmKey = cert.extractCSSMKey(fieldValue.allocator); 525 fieldValue.set(reinterpret_cast<uint8 *>(cssmKey), sizeof(CSSM_KEY)); 526 numFields = 1; 527 return true; 528} 529 530static void setField_PublicKeyStruct ( 531 DecodedItem &item, 532 const CssmData &fieldValue) 533{ 534 DecodedCert &cert = dynamic_cast<DecodedCert &>(item); 535 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO &dstKeyInfo = 536 cert.mCert.tbs.subjectPublicKeyInfo; 537 tbsSetCheck(dstKeyInfo.subjectPublicKey.Data, fieldValue, 538 sizeof(CSSM_KEY), "PubKeyStruct"); 539 540 CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR)fieldValue.data(); 541 if((cssmKey->KeyData.Data == NULL) || 542 (cssmKey->KeyData.Data == 0)) { 543 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); 544 } 545 CL_CSSMKeyToSubjPubKeyInfoNSS(*cssmKey, dstKeyInfo, cert.coder()); 546} 547 548static void freeField_PublicKeyStruct ( 549 CssmOwnedData &fieldValue) 550{ 551 CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR)fieldValue.data(); 552 CL_freeCSSMKey(cssmKey, fieldValue.allocator, false); 553} 554 555/*** 556 *** Signature 557 *** Format = raw bytes 558 *** read-only 559 ***/ 560static bool getField_Signature ( 561 DecodedItem &item, 562 unsigned index, // which occurrence (0 = first) 563 uint32 &numFields, // RETURNED 564 CssmOwnedData &fieldValue) // RETURNED 565{ 566 const DecodedCert &cert = dynamic_cast<const DecodedCert &>(item); 567 const CSSM_DATA &sigBits = cert.mCert.signature; 568 if(!tbsGetCheck(sigBits.Data, index)) { 569 return false; 570 } 571 fieldValue.copy(sigBits.Data, (sigBits.Length + 7) / 8); 572 numFields = 1; 573 return true; 574} 575 576/*** 577 *** end of field-specific triplets 578 ***/ 579 580/* 581 * Table to map OID to {get,set,free}field 582 */ 583typedef struct { 584 const CSSM_OID *fieldId; 585 getItemFieldFcn *getFcn; 586 setItemFieldFcn *setFcn; 587 freeFieldFcn *freeFcn; // OPTIONAL - NULL means just free the 588 // top-level data 589} oidToFieldFuncs; 590 591static const oidToFieldFuncs fieldFuncTable[] = { 592 { &CSSMOID_X509V1Version, 593 &getField_Version, &setField_Version, NULL }, 594 { &CSSMOID_X509V1SerialNumber, 595 &getField_SerialNumber, &setField_SerialNumber, NULL }, 596 { &CSSMOID_X509V1IssuerNameCStruct, 597 &getField_Issuer, &setField_Issuer, &freeField_RDN }, 598 { &CSSMOID_X509V1SubjectNameCStruct, 599 &getField_Subject, &setField_Subject, &freeField_RDN }, 600 { &CSSMOID_X509V1SignatureAlgorithmTBS, 601 &getField_TbsAlgId, &setField_TbsAlgId, &freeField_AlgId }, 602 { &CSSMOID_X509V1SignatureAlgorithm, 603 &getField_CertAlgId, &setField_ReadOnly, &freeField_AlgId }, 604 { &CSSMOID_X509V1ValidityNotBefore, 605 &getField_NotBefore, &setField_NotBefore, &freeField_Time }, 606 { &CSSMOID_X509V1ValidityNotAfter, 607 &getField_NotAfter, &setField_NotAfter, &freeField_Time }, 608 { &CSSMOID_X509V1CertificateIssuerUniqueId, 609 &getField_IssuerUniqueId, &setField_IssuerUniqueId, NULL }, 610 { &CSSMOID_X509V1CertificateSubjectUniqueId, 611 &getField_SubjectUniqueId, &setField_SubjectUniqueId, NULL }, 612 { &CSSMOID_X509V1SubjectPublicKeyCStruct, 613 &getField_PublicKeyInfo, &setField_PublicKeyInfo, &freeField_PublicKeyInfo }, 614 { &CSSMOID_CSSMKeyStruct, 615 &getField_PublicKeyStruct, &setField_PublicKeyStruct, 616 &freeField_PublicKeyStruct }, 617 { &CSSMOID_X509V1Signature, 618 &getField_Signature, &setField_ReadOnly, NULL }, 619 { &CSSMOID_X509V1IssuerName, 620 getFieldIssuerNorm, &setField_ReadOnly, NULL }, 621 { &CSSMOID_X509V1SubjectName, 622 getFieldSubjectNorm, &setField_ReadOnly, NULL }, 623 { &CSSMOID_X509V1IssuerNameStd, 624 getFieldIssuerStd, &setField_ReadOnly, NULL }, 625 { &CSSMOID_X509V1SubjectNameStd, 626 getFieldSubjectStd, &setField_ReadOnly, NULL }, 627 628 /* 629 * Extensions, implemented in CLCertExtensions.cpp 630 * When adding new ones, also add to: 631 * -- clOidToNssInfo() in CLFieldsCommon.cpp 632 * -- get/set/free functions in CLCertExtensions.{cpp,h} 633 */ 634 { &CSSMOID_KeyUsage, &getFieldKeyUsage, &setFieldKeyUsage, 635 &freeFieldSimpleExtension }, 636 { &CSSMOID_BasicConstraints, &getFieldBasicConstraints, 637 &setFieldBasicConstraints, &freeFieldSimpleExtension }, 638 { &CSSMOID_ExtendedKeyUsage, &getFieldExtKeyUsage, 639 &setFieldExtKeyUsage, &freeFieldExtKeyUsage } , 640 { &CSSMOID_SubjectKeyIdentifier, &getFieldSubjectKeyId, 641 &setFieldSubjectKeyId, &freeFieldSubjectKeyId } , 642 { &CSSMOID_AuthorityKeyIdentifier, &getFieldAuthorityKeyId, 643 &setFieldAuthorityKeyId, &freeFieldAuthorityKeyId } , 644 { &CSSMOID_SubjectAltName, &getFieldSubjAltName, 645 &setFieldSubjIssuerAltName, &freeFieldSubjIssuerAltName } , 646 { &CSSMOID_IssuerAltName, &getFieldIssuerAltName, 647 &setFieldSubjIssuerAltName, &freeFieldSubjIssuerAltName } , 648 { &CSSMOID_CertificatePolicies, &getFieldCertPolicies, 649 &setFieldCertPolicies, &freeFieldCertPolicies } , 650 { &CSSMOID_NetscapeCertType, &getFieldNetscapeCertType, 651 &setFieldNetscapeCertType, &freeFieldSimpleExtension } , 652 { &CSSMOID_CrlDistributionPoints, &getFieldCrlDistPoints, 653 &setFieldCrlDistPoints, &freeFieldCrlDistPoints }, 654 { &CSSMOID_X509V3CertificateExtensionCStruct, &getFieldUnknownExt, 655 &setFieldUnknownExt, &freeFieldUnknownExt }, 656 { &CSSMOID_AuthorityInfoAccess, &getFieldAuthInfoAccess, 657 &setFieldAuthInfoAccess, &freeFieldInfoAccess }, 658 { &CSSMOID_SubjectInfoAccess, &getFieldSubjInfoAccess, 659 &setFieldAuthInfoAccess, &freeFieldInfoAccess }, 660 { &CSSMOID_QC_Statements, &getFieldQualCertStatements, 661 &setFieldQualCertStatements, &freeFieldQualCertStatements }, 662 663 { &CSSMOID_NameConstraints, &getFieldNameConstraints, 664 &setFieldNameConstraints, &freeFieldNameConstraints }, 665 { &CSSMOID_PolicyMappings, &getFieldPolicyMappings, 666 &setFieldPolicyMappings, &freeFieldPolicyMappings }, 667 { &CSSMOID_PolicyConstraints, &getFieldPolicyConstraints, 668 &setFieldPolicyConstraints, &freeFieldPolicyConstraints }, 669 { &CSSMOID_InhibitAnyPolicy, &getFieldInhibitAnyPolicy, 670 &setFieldInhibitAnyPolicy, &freeFieldSimpleExtension }, 671 672}; 673 674#define NUM_KNOWN_FIELDS (sizeof(fieldFuncTable) / sizeof(oidToFieldFuncs)) 675#define NUM_STD_CERT_FIELDS 17 /* not including extensions */ 676 677/* map an OID to an oidToFieldFuncs */ 678static const oidToFieldFuncs *oidToFields( 679 const CssmOid &fieldId) 680{ 681 const oidToFieldFuncs *fieldTable = fieldFuncTable; 682 for(unsigned i=0; i<NUM_KNOWN_FIELDS; i++) { 683 if(fieldId == CssmData::overlay(*fieldTable->fieldId)) { 684 return fieldTable; 685 } 686 fieldTable++; 687 } 688#ifndef NDEBUG 689 clErrorLog("oidToFields: unknown OID (len=%d): %s\n", 690 (int)fieldId.length(), fieldId.toHex().c_str()); 691#endif 692 CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG); 693} 694 695 696/*** 697 *** Public functions 698 ***/ 699 700/* 701 * Obtain the index'th occurrence of field specified by fieldId in specified cert. 702 * Format of the returned field depends on fieldId. 703 * Returns total number of fieldId fields in the cert if index is 0. 704 * FieldValue assumed to be empty on entry. 705 * Returns true if specified field was found, else returns false. 706 */ 707bool DecodedCert::getCertFieldData( 708 const CssmOid &fieldId, // which field 709 unsigned index, // which occurrence (0 = first) 710 uint32 &numFields, // RETURNED 711 CssmOwnedData &fieldValue) // RETURNED 712{ 713 switch(mState) { 714 case IS_Empty: 715 case IS_Building: 716 clErrorLog("DecodedCert::getCertField: can't parse undecoded cert!"); 717 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); 718 case IS_DecodedAll: 719 case IS_DecodedTBS: 720 break; 721 } 722 const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId); 723 return fieldFuncs->getFcn(*this, index, numFields, fieldValue); 724} 725 726/* 727 * Set the field specified by fieldId in the specified Cert. 728 * Note no index - individual field routines either append (for extensions) 729 * or if field already set ::throwMe(for all others) 730 */ 731void DecodedCert::setCertField( 732 const CssmOid &fieldId, // which field 733 const CssmData &fieldValue) 734{ 735 switch(mState) { 736 case IS_Empty: // first time thru 737 mState = IS_Building; 738 break; 739 case IS_Building: // subsequent passes 740 break; 741 case IS_DecodedAll: 742 case IS_DecodedTBS: 743 clErrorLog("DecodedCert::setCertField: can't build on a decoded cert!"); 744 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); 745 } 746 if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) { 747 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); 748 } 749 const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId); 750 const CssmData &value = CssmData::overlay(fieldValue); 751 fieldFuncs->setFcn(*this, value); 752} 753 754/* 755 * Free the fieldId-specific data referred to by fieldValue->Data. 756 */ 757void DecodedCert::freeCertFieldData( 758 const CssmOid &fieldId, 759 CssmOwnedData &fieldValue) 760{ 761 if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) { 762 CssmError::throwMe(CSSM_ERRCODE_INVALID_FIELD_POINTER); 763 } 764 const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId); 765 if(fieldFuncs->freeFcn != NULL) { 766 /* optional - simple cases handled below */ 767 fieldFuncs->freeFcn(fieldValue); 768 } 769 fieldValue.reset(); 770 fieldValue.release(); 771 772} 773 774 775/* 776 * Common means to get all fields from a decoded cert. Used in 777 * CertGetAllTemplateFields and CertGetAllFields. 778 */ 779void DecodedCert::getAllParsedCertFields( 780 uint32 &NumberOfFields, // RETURNED 781 CSSM_FIELD_PTR &CertFields) // RETURNED 782{ 783 /* this is the max - some might be missing */ 784 uint32 maxFields = NUM_STD_CERT_FIELDS + mDecodedExtensions.numExtensions(); 785 CSSM_FIELD_PTR outFields = (CSSM_FIELD_PTR)mAlloc.malloc(maxFields * sizeof(CSSM_FIELD)); 786 787 /* 788 * We'll be copying oids and values for fields we find into 789 * outFields; current number of valid fields found in numOutFields. 790 */ 791 memset(outFields, 0, maxFields * sizeof(CSSM_FIELD)); 792 uint32 numOutFields = 0; 793 CSSM_FIELD_PTR currOutField; 794 uint32 currOidDex; 795 const CSSM_OID *currOid; 796 CssmAutoData aData(mAlloc); // for malloc/copy of outgoing data 797 798 /* query for each OID we know about */ 799 for(currOidDex=0; currOidDex<NUM_KNOWN_FIELDS; currOidDex++) { 800 const oidToFieldFuncs *fieldFuncs = &fieldFuncTable[currOidDex]; 801 currOid = fieldFuncs->fieldId; 802 uint32 numFields; // for THIS oid 803 804 /* 805 * Return false if field not there, which is not an error here. 806 * Actual exceptions are fatal. 807 */ 808 if(!fieldFuncs->getFcn(*this, 809 0, // index - looking for first one 810 numFields, 811 aData)) { 812 continue; 813 } 814 815 /* got some data for this oid - copy it and oid to outgoing CertFields */ 816 assert(numOutFields < maxFields); 817 currOutField = &outFields[numOutFields]; 818 currOutField->FieldValue = aData.release(); 819 aData.copy(*currOid); 820 currOutField->FieldOid = aData.release(); 821 numOutFields++; 822 823 /* if more fields are available for this OID, snag them too */ 824 for(uint32 fieldDex=1; fieldDex<numFields; fieldDex++) { 825 /* note this should always succeed */ 826 bool brtn = fieldFuncs->getFcn(*this, 827 fieldDex, 828 numFields, // shouldn't change 829 aData); 830 if(!brtn) { 831 clErrorLog("getAllParsedCertFields: index screwup"); 832 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); 833 } 834 assert(numOutFields < maxFields); 835 currOutField = &outFields[numOutFields]; 836 currOutField->FieldValue = aData.release(); 837 aData.copy(*currOid); 838 currOutField->FieldOid = aData.release(); 839 numOutFields++; 840 } /* multiple fields for currOid */ 841 } /* for each known OID */ 842 843 NumberOfFields = numOutFields; 844 CertFields = outFields; 845} 846 847void 848DecodedCert::describeFormat( 849 Allocator &alloc, 850 uint32 &NumberOfFields, 851 CSSM_OID_PTR &OidList) 852{ 853 /* malloc in app's space, do deep copy (including ->Data) */ 854 CSSM_OID_PTR oidList = (CSSM_OID_PTR)alloc.malloc( 855 NUM_KNOWN_FIELDS * sizeof(CSSM_OID)); 856 memset(oidList, 0, NUM_KNOWN_FIELDS * sizeof(CSSM_OID)); 857 for(unsigned i=0; i<NUM_KNOWN_FIELDS; i++) { 858 CssmAutoData oidCopy(alloc, *fieldFuncTable[i].fieldId); 859 oidList[i] = oidCopy.release(); 860 } 861 NumberOfFields = NUM_KNOWN_FIELDS; 862 OidList = oidList; 863} 864