1/* 2 * Copyright (c) 2000-2001,2011,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// Apple X.509 CRL-related session functions. 21// 22 23#include "AppleX509CLSession.h" 24#include "clNssUtils.h" 25#include "clNameUtils.h" 26 27void 28AppleX509CLSession::CrlDescribeFormat( 29 uint32 &NumberOfFields, 30 CSSM_OID_PTR &OidList) 31{ 32 DecodedCrl::describeFormat(*this, NumberOfFields, OidList); 33} 34 35 36void 37AppleX509CLSession::CrlGetAllFields( 38 const CssmData &Crl, 39 uint32 &NumberOfCrlFields, 40 CSSM_FIELD_PTR &CrlFields) 41{ 42 class DecodedCrl decodedCrl(*this, Crl); 43 decodedCrl.getAllParsedCrlFields(NumberOfCrlFields, CrlFields); 44} 45 46 47CSSM_HANDLE 48AppleX509CLSession::CrlGetFirstFieldValue( 49 const CssmData &Crl, 50 const CssmData &CrlField, 51 uint32 &NumberOfMatchedFields, 52 CSSM_DATA_PTR &Value) 53{ 54 NumberOfMatchedFields = 0; 55 Value = NULL; 56 CssmAutoData aData(*this); 57 58 DecodedCrl *decodedCrl = new DecodedCrl(*this, Crl); 59 uint32 numMatches; 60 61 /* this returns false if field not there, throws on bad OID */ 62 bool brtn; 63 try { 64 brtn = decodedCrl->getCrlFieldData(CrlField, 65 0, // index 66 numMatches, 67 aData); 68 } 69 catch (...) { 70 delete decodedCrl; 71 throw; 72 } 73 if(!brtn) { 74 delete decodedCrl; 75 return CSSM_INVALID_HANDLE; 76 } 77 78 /* cook up a CLCachedCRL, stash it in cache */ 79 CLCachedCRL *cachedCrl = new CLCachedCRL(*decodedCrl); 80 cacheMap.addEntry(*cachedCrl, cachedCrl->handle()); 81 82 /* cook up a CLQuery, stash it */ 83 CLQuery *query = new CLQuery( 84 CLQ_CRL, 85 CrlField, 86 numMatches, 87 false, // isFromCache 88 cachedCrl->handle()); 89 queryMap.addEntry(*query, query->handle()); 90 91 /* success - copy field data to outgoing Value */ 92 Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); 93 *Value = aData.release(); 94 NumberOfMatchedFields = numMatches; 95 return query->handle(); 96} 97 98 99bool 100AppleX509CLSession::CrlGetNextFieldValue( 101 CSSM_HANDLE ResultsHandle, 102 CSSM_DATA_PTR &Value) 103{ 104 /* fetch & validate the query */ 105 CLQuery *query = queryMap.lookupEntry(ResultsHandle); 106 if(query == NULL) { 107 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); 108 } 109 if(query->queryType() != CLQ_CRL) { 110 clErrorLog("CrlGetNextFieldValue: bad queryType (%d)", 111 (int)query->queryType()); 112 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); 113 } 114 if(query->nextIndex() >= query->numFields()) { 115 return false; 116 } 117 118 /* fetch the associated cached CRL */ 119 CLCachedCRL *cachedCrl = lookupCachedCRL(query->cachedObject()); 120 uint32 dummy; 121 CssmAutoData aData(*this); 122 if(!cachedCrl->crl().getCrlFieldData(query->fieldId(), 123 query->nextIndex(), 124 dummy, 125 aData)) { 126 return false; 127 } 128 129 /* success - copy field data to outgoing Value */ 130 Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); 131 *Value = aData.release(); 132 query->incrementIndex(); 133 return true; 134} 135 136 137void 138AppleX509CLSession::IsCertInCrl( 139 const CssmData &Cert, 140 const CssmData &Crl, 141 CSSM_BOOL &CertFound) 142{ 143 /* 144 * Decode the two entities. Note that doing it this way incurs 145 * the unnecessary (for our purposes) overhead of decoding 146 * extensions, but doing it this way is so spiffy that I can't 147 * resist. 148 */ 149 DecodedCert decodedCert(*this, Cert); 150 DecodedCrl decodedCrl(*this, Crl); 151 152 NSS_TBSCertificate &tbsCert = decodedCert.mCert.tbs; 153 NSS_TBSCrl &tbsCrl = decodedCrl.mCrl.tbs; 154 155 /* trivial case - empty CRL */ 156 unsigned numCrlEntries = 157 clNssArraySize((const void **)tbsCrl.revokedCerts); 158 if(numCrlEntries == 0) { 159 clFieldLog("IsCertInCrl: empty CRL"); 160 CertFound = CSSM_FALSE; 161 return; 162 } 163 164 /* 165 * Get normalized and encoded versions of issuer names. 166 * Since the decoded entities are local, we can normalize in place. 167 */ 168 CssmAutoData encCertIssuer(*this); 169 CssmAutoData encCrlIssuer(*this); 170 try { 171 /* snag a handy temp allocator */ 172 SecNssCoder &coder = decodedCert.coder(); 173 CL_normalizeX509NameNSS(tbsCert.issuer, coder); 174 PRErrorCode prtn = SecNssEncodeItemOdata(&tbsCert.issuer, 175 kSecAsn1NameTemplate, encCertIssuer); 176 if(prtn) { 177 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); 178 } 179 180 CL_normalizeX509NameNSS(tbsCrl.issuer, coder); 181 prtn = SecNssEncodeItemOdata(&tbsCrl.issuer, 182 kSecAsn1NameTemplate, encCrlIssuer); 183 if(prtn) { 184 CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); 185 } 186 } 187 catch(...) { 188 clFieldLog("IsCertInCrl: normalize failure"); 189 throw; 190 } 191 192 /* issuer names match? */ 193 CertFound = CSSM_FALSE; 194 if(encCertIssuer.get() != encCrlIssuer.get()) { 195 clFieldLog("IsCertInCrl: issuer name mismatch"); 196 return; 197 } 198 199 /* is this cert's serial number in the CRL? */ 200 CSSM_DATA &certSerial = tbsCert.serialNumber; 201 for(unsigned dex=0; dex<numCrlEntries; dex++) { 202 NSS_RevokedCert *revokedCert = tbsCrl.revokedCerts[dex]; 203 assert(revokedCert != NULL); 204 CSSM_DATA &revokedSerial = revokedCert->userCertificate; 205 if(clCompareCssmData(&certSerial, &revokedSerial)) { 206 /* success */ 207 CertFound = CSSM_TRUE; 208 break; 209 } 210 } 211} 212 213#pragma mark --- Cached --- 214 215void 216AppleX509CLSession::CrlCache( 217 const CssmData &Crl, 218 CSSM_HANDLE &CrlHandle) 219{ 220 DecodedCrl *decodedCrl = new DecodedCrl(*this, Crl); 221 222 /* cook up a CLCachedCRL, stash it in cache */ 223 CLCachedCRL *cachedCrl = new CLCachedCRL(*decodedCrl); 224 cacheMap.addEntry(*cachedCrl, cachedCrl->handle()); 225 CrlHandle = cachedCrl->handle(); 226} 227 228/* 229 * FIXME - CrlRecordIndex not supported, it'll require mods to 230 * the DecodedCrl::getCrlFieldData mechanism 231 */ 232CSSM_HANDLE 233AppleX509CLSession::CrlGetFirstCachedFieldValue( 234 CSSM_HANDLE CrlHandle, 235 const CssmData *CrlRecordIndex, 236 const CssmData &CrlField, 237 uint32 &NumberOfMatchedFields, 238 CSSM_DATA_PTR &Value) 239{ 240 if(CrlRecordIndex != NULL) { 241 /* not yet */ 242 CssmError::throwMe(CSSMERR_CL_INVALID_CRL_INDEX); 243 } 244 245 /* fetch the associated cached CRL */ 246 CLCachedCRL *cachedCrl = lookupCachedCRL(CrlHandle); 247 if(cachedCrl == NULL) { 248 CssmError::throwMe(CSSMERR_CL_INVALID_CACHE_HANDLE); 249 } 250 251 CssmAutoData aData(*this); 252 uint32 numMatches; 253 254 /* this returns false if field not there, throws on bad OID */ 255 if(!cachedCrl->crl().getCrlFieldData(CrlField, 256 0, // index 257 numMatches, 258 aData)) { 259 return CSSM_INVALID_HANDLE; 260 } 261 262 /* cook up a CLQuery, stash it */ 263 CLQuery *query = new CLQuery( 264 CLQ_CRL, 265 CrlField, 266 numMatches, 267 true, // isFromCache 268 cachedCrl->handle()); 269 queryMap.addEntry(*query, query->handle()); 270 271 /* success - copy field data to outgoing Value */ 272 Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); 273 *Value = aData.release(); 274 NumberOfMatchedFields = numMatches; 275 return query->handle(); 276} 277 278 279bool 280AppleX509CLSession::CrlGetNextCachedFieldValue( 281 CSSM_HANDLE ResultsHandle, 282 CSSM_DATA_PTR &Value) 283{ 284 /* Identical to, so just call... */ 285 return CrlGetNextFieldValue(ResultsHandle, Value); 286} 287 288 289void 290AppleX509CLSession::IsCertInCachedCrl( 291 const CssmData &Cert, 292 CSSM_HANDLE CrlHandle, 293 CSSM_BOOL &CertFound, 294 CssmData &CrlRecordIndex) 295{ 296 unimplemented(); 297} 298 299 300void 301AppleX509CLSession::CrlAbortCache( 302 CSSM_HANDLE CrlHandle) 303{ 304 /* fetch the associated cached CRL, remove from map, delete it */ 305 CLCachedCRL *cachedCrl = lookupCachedCRL(CrlHandle); 306 if(cachedCrl == NULL) { 307 CssmError::throwMe(CSSMERR_CL_INVALID_CACHE_HANDLE); 308 } 309 cacheMap.removeEntry(cachedCrl->handle()); 310 delete cachedCrl; 311} 312 313 314void 315AppleX509CLSession::CrlAbortQuery( 316 CSSM_HANDLE ResultsHandle) 317{ 318 /* fetch & validate the query */ 319 CLQuery *query = queryMap.lookupEntry(ResultsHandle); 320 if(query == NULL) { 321 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); 322 } 323 if(query->queryType() != CLQ_CRL) { 324 clErrorLog("CrlAbortQuery: bad queryType (%d)", (int)query->queryType()); 325 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); 326 } 327 328 if(!query->fromCache()) { 329 /* the associated cached CRL was created just for this query; dispose */ 330 CLCachedCRL *cachedCrl = lookupCachedCRL(query->cachedObject()); 331 if(cachedCrl == NULL) { 332 /* should never happen */ 333 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); 334 } 335 cacheMap.removeEntry(cachedCrl->handle()); 336 delete cachedCrl; 337 } 338 queryMap.removeEntry(query->handle()); 339 delete query; 340} 341 342#pragma mark --- Template --- 343 344void 345AppleX509CLSession::CrlCreateTemplate( 346 uint32 NumberOfFields, 347 const CSSM_FIELD *CrlTemplate, 348 CssmData &NewCrl) 349{ 350 unimplemented(); 351} 352 353 354void 355AppleX509CLSession::CrlSetFields( 356 uint32 NumberOfFields, 357 const CSSM_FIELD *CrlTemplate, 358 const CssmData &OldCrl, 359 CssmData &ModifiedCrl) 360{ 361 unimplemented(); 362} 363 364 365void 366AppleX509CLSession::CrlAddCert( 367 CSSM_CC_HANDLE CCHandle, 368 const CssmData &Cert, 369 uint32 NumberOfFields, 370 const CSSM_FIELD CrlEntryFields[], 371 const CssmData &OldCrl, 372 CssmData &NewCrl) 373{ 374 unimplemented(); 375} 376 377 378void 379AppleX509CLSession::CrlRemoveCert( 380 const CssmData &Cert, 381 const CssmData &OldCrl, 382 CssmData &NewCrl) 383{ 384 unimplemented(); 385} 386 387 388void 389AppleX509CLSession::CrlGetAllCachedRecordFields( 390 CSSM_HANDLE CrlHandle, 391 const CssmData &CrlRecordIndex, 392 uint32 &NumberOfFields, 393 CSSM_FIELD_PTR &CrlFields) 394{ 395 unimplemented(); 396} 397 398/* 399 * These are functionally identical to the corresponding 400 * Cert functions. 401 */ 402void 403AppleX509CLSession::CrlVerifyWithKey( 404 CSSM_CC_HANDLE CCHandle, 405 const CssmData &CrlToBeVerified) 406{ 407 CertVerifyWithKey(CCHandle, CrlToBeVerified); 408} 409 410 411void 412AppleX509CLSession::CrlVerify( 413 CSSM_CC_HANDLE CCHandle, 414 const CssmData &CrlToBeVerified, 415 const CssmData *SignerCert, 416 const CSSM_FIELD *VerifyScope, 417 uint32 ScopeSize) 418{ 419 CertVerify(CCHandle, CrlToBeVerified, SignerCert, VerifyScope, 420 ScopeSize); 421} 422 423void 424AppleX509CLSession::CrlSign( 425 CSSM_CC_HANDLE CCHandle, 426 const CssmData &UnsignedCrl, 427 const CSSM_FIELD *SignScope, 428 uint32 ScopeSize, 429 CssmData &SignedCrl) 430{ 431 unimplemented(); 432} 433 434 435 436 437