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