1/* 2 * Copyright (c) 2002-2011 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 * CLFieldsCommon.h - get/set/free routines common to certs and CRLs 21 */ 22 23#include "CLFieldsCommon.h" 24#include "clNameUtils.h" 25#include "clNssUtils.h" 26#include "AppleX509CLSession.h" 27#include <Security/cssmapple.h> 28#include <Security/oidscert.h> 29#include <Security/nameTemplates.h> 30#include <Security/certExtensionTemplates.h> 31#include <Security/SecAsn1Templates.h> 32 33/* 34 * Table to map an OID to the info needed to decode the 35 * associated extension 36 */ 37typedef struct { 38 const CSSM_OID &oid; 39 unsigned nssObjLen; 40 const SecAsn1Template *templ; 41} NssExtenInfo; 42 43static const NssExtenInfo nssExtenInfo[] = { 44 { CSSMOID_KeyUsage, 45 sizeof(CSSM_DATA), 46 kSecAsn1KeyUsageTemplate }, 47 { CSSMOID_BasicConstraints, 48 sizeof(NSS_BasicConstraints), 49 kSecAsn1BasicConstraintsTemplate }, 50 { CSSMOID_ExtendedKeyUsage, 51 sizeof(NSS_ExtKeyUsage), 52 kSecAsn1ExtKeyUsageTemplate }, 53 { CSSMOID_SubjectKeyIdentifier, 54 sizeof(CSSM_DATA), 55 kSecAsn1SubjectKeyIdTemplate }, 56 { CSSMOID_AuthorityKeyIdentifier, 57 sizeof(NSS_AuthorityKeyId), 58 kSecAsn1AuthorityKeyIdTemplate }, 59 { CSSMOID_SubjectAltName, 60 sizeof(NSS_GeneralNames), 61 kSecAsn1GeneralNamesTemplate }, 62 { CSSMOID_IssuerAltName, 63 sizeof(NSS_GeneralNames), 64 kSecAsn1GeneralNamesTemplate }, 65 { CSSMOID_CertificatePolicies, 66 sizeof(NSS_CertPolicies), 67 kSecAsn1CertPoliciesTemplate }, 68 { CSSMOID_NetscapeCertType, 69 sizeof(CSSM_DATA), 70 kSecAsn1NetscapeCertTypeTemplate }, 71 { CSSMOID_CrlDistributionPoints, 72 sizeof(NSS_CRLDistributionPoints), 73 kSecAsn1CRLDistributionPointsTemplate }, 74 { CSSMOID_CertIssuer, 75 sizeof(NSS_GeneralNames), 76 kSecAsn1GeneralNamesTemplate }, 77 { CSSMOID_AuthorityInfoAccess, 78 sizeof(NSS_AuthorityInfoAccess), 79 kSecAsn1AuthorityInfoAccessTemplate }, 80 { CSSMOID_SubjectInfoAccess, 81 sizeof(NSS_AuthorityInfoAccess), 82 kSecAsn1AuthorityInfoAccessTemplate }, 83 /* CRL extensions */ 84 { CSSMOID_CrlNumber, 85 sizeof(CSSM_DATA), 86 kSecAsn1IntegerTemplate }, 87 { CSSMOID_IssuingDistributionPoint, 88 sizeof(NSS_IssuingDistributionPoint), 89 kSecAsn1IssuingDistributionPointTemplate }, 90 { CSSMOID_HoldInstructionCode, 91 sizeof(CSSM_OID), 92 kSecAsn1ObjectIDTemplate }, 93 { CSSMOID_CrlReason, 94 sizeof(CSSM_DATA), 95 kSecAsn1EnumeratedTemplate }, 96 { CSSMOID_DeltaCrlIndicator, 97 sizeof(CSSM_DATA), 98 kSecAsn1IntegerTemplate }, 99 { CSSMOID_InvalidityDate, 100 sizeof(CSSM_DATA), 101 kSecAsn1GeneralizedTimeTemplate }, 102 { CSSMOID_QC_Statements, 103 sizeof(NSS_QC_Statements), 104 kSecAsn1QC_StatementsTemplate }, 105 { CSSMOID_NameConstraints, 106 sizeof(NSS_NameConstraints), 107 kSecAsn1NameConstraintsTemplate }, 108 { CSSMOID_PolicyMappings, 109 sizeof(NSS_PolicyMappings), 110 kSecAsn1PolicyMappingsTemplate }, 111 { CSSMOID_PolicyConstraints, 112 sizeof(NSS_PolicyConstraints), 113 kSecAsn1PolicyConstraintsTemplate }, 114 { CSSMOID_InhibitAnyPolicy, 115 sizeof(CSSM_DATA), 116 kSecAsn1IntegerTemplate }, 117}; 118 119#define NUM_NSS_EXTEN_INFOS (sizeof(nssExtenInfo) / sizeof(nssExtenInfo[0])) 120 121/* 122 * Returns true if we find the OID. 123 */ 124bool clOidToNssInfo( 125 const CSSM_OID &oid, 126 unsigned &nssObjLen, // RETURNED 127 const SecAsn1Template *&templ) // RETURNED 128{ 129 for(unsigned dex=0; dex<NUM_NSS_EXTEN_INFOS; dex++) { 130 const NssExtenInfo &info = nssExtenInfo[dex]; 131 if(clCompareCssmData(&info.oid, &oid)) { 132 nssObjLen = info.nssObjLen; 133 templ = info.templ; 134 return true; 135 } 136 } 137 return false; 138} 139 140 141 142/* 143 * Common code to pass info from a DecodedExten back to app. 144 * Called from getField*(). 145 */ 146void getFieldExtenCommon( 147 void *cdsaObj, // e.g. CE_KeyUsage 148 // NULL for berEncoded 149 const DecodedExten &decodedExt, 150 CssmOwnedData &fieldValue) 151{ 152 CSSM_X509_EXTENSION_PTR cssmExt; 153 Allocator &alloc = fieldValue.allocator; 154 CssmData &fdata = fieldValue.get(); 155 156 cssmExt = (CSSM_X509_EXTENSION_PTR)alloc. 157 malloc(sizeof(CSSM_X509_EXTENSION)); 158 fdata.Data = (uint8 *)cssmExt; 159 fdata.Length = sizeof(CSSM_X509_EXTENSION); 160 decodedExt.convertToCdsa(cdsaObj, cssmExt, alloc); 161} 162 163/* 164 * Common code for top of setField* and freeField*(). 165 */ 166CSSM_X509_EXTENSION_PTR verifySetFreeExtension( 167 const CssmData &fieldValue, 168 bool berEncoded) // false: value in value.parsedValue 169 // true : value in BERValue 170{ 171 if(fieldValue.length() != sizeof(CSSM_X509_EXTENSION)) { 172 clFieldLog("Set/FreeExtension: bad length : exp %d got %d", 173 (int)sizeof(CSSM_X509_EXTENSION), (int)fieldValue.length()); 174 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); 175 } 176 CSSM_X509_EXTENSION_PTR cssmExt = 177 reinterpret_cast<CSSM_X509_EXTENSION_PTR>(fieldValue.data()); 178 if(berEncoded) { 179 if(cssmExt->BERvalue.Data == NULL) { 180 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); 181 } 182 } 183 else { 184 if(cssmExt->value.parsedValue == NULL) { 185 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); 186 } 187 } 188 return cssmExt; 189} 190 191/* 192 * Common free code for all extensions. Extension-specific code must 193 * free anything beyond cdsaExt->Value.parsedValue, then we free everything 194 * else (except the extension struct itself, which is freed by 195 * DecodedCert::freeCertFieldData()). 196 * The value union may contain a parsed value, or a CSSM_X509EXT_TAGandVALUE; 197 * wed ont' care, we just free it. 198 */ 199void freeFieldExtenCommon( 200 CSSM_X509_EXTENSION_PTR exten, 201 Allocator &alloc) 202{ 203 alloc.free(exten->extnId.Data); 204 alloc.free(exten->BERvalue.Data); // may be NULL 205 alloc.free(exten->value.parsedValue); // may be NULL 206} 207 208/* 209 * One common free for extensions whose parsed value doesn't go any deeper 210 * than cssmExt->value.parsedValue. 211 */ 212void freeFieldSimpleExtension ( 213 CssmOwnedData &fieldValue) 214{ 215 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, 216 false); 217 freeFieldExtenCommon(cssmExt, fieldValue.allocator); 218} 219 220 221/*** 222 *** Common code for get/set subject/issuer name (C struct version) 223 *** Format = CSSM_X509_NAME 224 *** class Name from sm_x501if 225 ***/ 226bool getField_RDN_NSS ( 227 const NSS_Name &nssName, 228 CssmOwnedData &fieldValue) // RETURNED 229{ 230 /* alloc top-level CSSM_X509_NAME */ 231 Allocator &alloc = fieldValue.allocator; 232 fieldValue.malloc(sizeof(CSSM_X509_NAME)); 233 CSSM_X509_NAME_PTR cssmName = (CSSM_X509_NAME_PTR)fieldValue.data(); 234 235 CL_nssNameToCssm(nssName, *cssmName, alloc); 236 return true; 237} 238 239void freeField_RDN ( 240 CssmOwnedData &fieldValue) 241{ 242 if(fieldValue.data() == NULL) { 243 return; 244 } 245 if(fieldValue.length() != sizeof(CSSM_X509_NAME)) { 246 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); 247 } 248 Allocator &alloc = fieldValue.allocator; 249 CSSM_X509_NAME_PTR x509Name = (CSSM_X509_NAME_PTR)fieldValue.data(); 250 CL_freeX509Name(x509Name, alloc); 251 252 /* top-level x509Name pointer freed by freeCertFieldData() */ 253} 254 255/*** 256 *** Common code for Issuer Name, Subject Name (normalized and encoded 257 *** version) 258 *** Format = CSSM_DATA containing the DER encoding of the normalized name 259 ***/ 260bool getField_normRDN_NSS ( 261 const CSSM_DATA &derName, 262 uint32 &numFields, // RETURNED (if successful, 0 or 1) 263 CssmOwnedData &fieldValue) // RETURNED 264{ 265 if(derName.Data == NULL) { 266 /* This can happen during CertGetAllTemplateFields() because 267 * the normalized fields are only set up during cert/CRL decode */ 268 return false; 269 } 270 271 /* 272 * First make a temp decoded copy which we'll be manipulating. 273 */ 274 SecNssCoder coder; 275 NSS_Name decodedName; 276 277 memset(&decodedName, 0, sizeof(decodedName)); 278 PRErrorCode prtn = coder.decodeItem(derName, kSecAsn1NameTemplate, &decodedName); 279 if(prtn) { 280 /* 281 * Actually should never happen since this same bag of bits successfully 282 * decoded when the cert as a whole was decoded... 283 */ 284 clErrorLog("getField_normRDN decode error\n"); 285 CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); 286 287 } 288 289 /* normalize */ 290 CL_normalizeX509NameNSS(decodedName, coder); 291 292 /* encode result */ 293 prtn = SecNssEncodeItemOdata(&decodedName, kSecAsn1NameTemplate, fieldValue); 294 if(prtn) { 295 clErrorLog("getField_normRDN encode error\n"); 296 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); 297 } 298 numFields = 1; 299 return true; 300} 301 302/*** 303 *** Common code for Time fields - Validity not before, Not After, 304 *** This Update, Next Update 305 *** Format: CSSM_X509_TIME 306 ***/ 307bool getField_TimeNSS ( 308 const NSS_Time &nssTime, 309 unsigned index, // which occurrence (0 = first) 310 uint32 &numFields, // RETURNED 311 CssmOwnedData &fieldValue) // RETURNED 312{ 313 if(!tbsGetCheck(nssTime.item.Data, index)) { 314 return false; 315 } 316 Allocator &alloc = fieldValue.allocator; 317 fieldValue.malloc(sizeof(CSSM_X509_TIME)); 318 CSSM_X509_TIME *cssmTime = 319 (CSSM_X509_TIME *)fieldValue.data(); 320 if(CL_nssTimeToCssm(nssTime, *cssmTime, alloc)) { 321 numFields = 1; 322 return true; 323 } 324 else { 325 return false; 326 } 327} 328 329void setField_TimeNSS ( 330 const CssmData &fieldValue, 331 NSS_Time &nssTime, 332 SecNssCoder &coder) 333{ 334 CSSM_X509_TIME *cssmTime = 335 (CSSM_X509_TIME *)fieldValue.data(); 336 CL_cssmTimeToNss(*cssmTime, nssTime, coder); 337} 338 339void freeField_Time ( 340 CssmOwnedData &fieldValue) 341{ 342 CSSM_X509_TIME *cssmTime = (CSSM_X509_TIME *)fieldValue.data(); 343 if(cssmTime == NULL) { 344 return; 345 } 346 if(fieldValue.length() != sizeof(CSSM_X509_TIME)) { 347 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); 348 } 349 CL_freeCssmTime(cssmTime, fieldValue.allocator); 350} 351 352/*** 353 *** TBS AlgId, Signature AlgId 354 *** Format = CSSM_X509_ALGORITHM_IDENTIFIER 355 ***/ 356void getField_AlgIdNSS ( 357 const CSSM_X509_ALGORITHM_IDENTIFIER &srcAlgId, 358 CssmOwnedData &fieldValue) // RETURNED 359{ 360 Allocator &alloc = fieldValue.allocator; 361 fieldValue.malloc(sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)); 362 CSSM_X509_ALGORITHM_IDENTIFIER *destAlgId = 363 (CSSM_X509_ALGORITHM_IDENTIFIER *)fieldValue.data(); 364 CL_copyAlgId(srcAlgId, *destAlgId, alloc); 365} 366 367void setField_AlgIdNSS ( 368 const CssmData &fieldValue, 369 CSSM_X509_ALGORITHM_IDENTIFIER &dstAlgId, 370 SecNssCoder &coder) 371{ 372 CSSM_X509_ALGORITHM_IDENTIFIER *srcAlgId = 373 (CSSM_X509_ALGORITHM_IDENTIFIER *)fieldValue.data(); 374 /* allocator for this coder */ 375 ArenaAllocator areanAlloc(coder); 376 CL_copyAlgId(*srcAlgId, dstAlgId, areanAlloc); 377} 378 379void freeField_AlgId ( 380 CssmOwnedData &fieldValue) 381{ 382 CSSM_X509_ALGORITHM_IDENTIFIER *cssmAlgId = 383 (CSSM_X509_ALGORITHM_IDENTIFIER *)fieldValue.data(); 384 if(cssmAlgId == NULL) { 385 return; 386 } 387 if(fieldValue.length() != sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)) { 388 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); 389 } 390 Allocator &alloc = fieldValue.allocator; 391 alloc.free(cssmAlgId->algorithm.Data); 392 alloc.free(cssmAlgId->parameters.Data); 393 memset(cssmAlgId, 0, sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)); 394} 395 396/* 397 * Routines for common validity checking for certificateToSign fields. 398 * 399 * Call from setField*: verify field isn't already set, optionally validate 400 * input length 401 */ 402void tbsSetCheck( 403 void *fieldToSet, 404 const CssmData &fieldValue, 405 uint32 expLength, 406 const char *op) 407{ 408 if(fieldToSet != NULL) { 409 /* can't add another */ 410 clErrorLog("setField(%s): field already set", op); 411 CssmError::throwMe(CSSMERR_CL_INVALID_NUMBER_OF_FIELDS); 412 } 413 if((expLength != 0) && (fieldValue.length() != expLength)) { 414 clErrorLog("setField(%s): bad length : exp %d got %d", 415 op, (int)expLength, (int)fieldValue.length()); 416 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER); 417 } 418} 419 420/* 421 * Call from getField* for unique fields - detect missing field or 422 * index out of bounds. 423 */ 424bool tbsGetCheck( 425 const void *requiredField, 426 uint32 reqIndex) 427{ 428 if((requiredField == NULL) || (reqIndex != 0)) { 429 return false; 430 } 431 else { 432 return true; 433 } 434} 435 436/*** 437 *** unknown extensions 438 *** CDSA format: raw bytes in a CSSM_DATA. This data is the BER-encoding of 439 *** some extension struct we don't know about. 440 *** NSS format CSSM_DATA 441 *** OID CSSMOID_X509V3CertificateExtensionCStruct 442 ***/ 443 444void setFieldUnknownExt( 445 DecodedItem &cert, 446 const CssmData &fieldValue) 447{ 448 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, true); 449 SecNssCoder &coder = cert.coder(); 450 CSSM_DATA *rawExtn = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA)); 451 coder.allocCopyItem(cssmExt->BERvalue, *rawExtn); 452 cert.addExtension(NULL, cssmExt->extnId, cssmExt->critical, 453 true, NULL /* no template */, rawExtn); 454} 455 456bool getFieldUnknownExt( 457 DecodedItem &cert, 458 unsigned index, // which occurrence (0 = first) 459 uint32 &numFields, // RETURNED 460 CssmOwnedData &fieldValue) 461{ 462 uint8 noOidDataLikeThis[2] = {1, 2}; // a dummy argument 463 CSSM_OID noOidLikeThis = {2, noOidDataLikeThis}; 464 const DecodedExten *decodedExt = 465 cert.DecodedItem::findDecodedExt(noOidLikeThis, 466 true, index, numFields); 467 if(decodedExt == NULL) { 468 return false; 469 } 470 getFieldExtenCommon(NULL, *decodedExt, fieldValue); 471 return true; 472} 473 474void freeFieldUnknownExt ( 475 CssmOwnedData &fieldValue) 476{ 477 CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, true); 478 Allocator &alloc = fieldValue.allocator; 479 freeFieldExtenCommon(cssmExt, alloc); // frees extnId, parsedValue, BERvalue 480} 481 482/* setField for read-only OIDs (i.e., the ones in cert/CRL, not TBS) */ 483void setField_ReadOnly ( 484 DecodedItem &item, 485 const CssmData &fieldValue) 486{ 487 clErrorLog("Attempt to set a read-only field"); 488 CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG); 489} 490 491bool getField_Unimplemented ( 492 DecodedItem &item, 493 unsigned index, // which occurrence (0 = first) 494 uint32 &numFields, // RETURNED 495 CssmOwnedData &fieldValue) // RETURNED 496{ 497 clErrorLog("Attempt to get an unimplemented field"); 498 CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG); 499} 500 501 502 503