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// Session_Cert.cpp - cert-related session functions. 21// 22 23#include "AppleX509CLSession.h" 24#include "DecodedCert.h" 25#include "DecodedCrl.h" 26#include "CLCachedEntry.h" 27#include "cldebugging.h" 28#include <Security/oidscert.h> 29 30void 31AppleX509CLSession::CertDescribeFormat( 32 uint32 &NumberOfFields, 33 CSSM_OID_PTR &OidList) 34{ 35 DecodedCert::describeFormat(*this, NumberOfFields, OidList); 36} 37 38void 39AppleX509CLSession::CertGetAllFields( 40 const CssmData &Cert, 41 uint32 &NumberOfFields, 42 CSSM_FIELD_PTR &CertFields) 43{ 44 DecodedCert decodedCert(*this, Cert); 45 decodedCert.getAllParsedCertFields(NumberOfFields, CertFields); 46} 47 48 49CSSM_HANDLE 50AppleX509CLSession::CertGetFirstFieldValue( 51 const CssmData &EncodedCert, 52 const CssmData &CertField, 53 uint32 &NumberOfMatchedFields, 54 CSSM_DATA_PTR &Value) 55{ 56 NumberOfMatchedFields = 0; 57 Value = NULL; 58 CssmAutoData aData(*this); 59 60 DecodedCert *decodedCert = new DecodedCert(*this, EncodedCert); 61 uint32 numMatches; 62 63 /* this returns false if field not there, throws on bad OID */ 64 bool brtn; 65 try { 66 brtn = decodedCert->getCertFieldData(CertField, 67 0, // index 68 numMatches, 69 aData); 70 } 71 catch (...) { 72 delete decodedCert; 73 throw; 74 } 75 if(!brtn) { 76 delete decodedCert; 77 return CSSM_INVALID_HANDLE; 78 } 79 80 /* cook up a CLCachedCert, stash it in cache */ 81 CLCachedCert *cachedCert = new CLCachedCert(*decodedCert); 82 cacheMap.addEntry(*cachedCert, cachedCert->handle()); 83 84 /* cook up a CLQuery, stash it */ 85 CLQuery *query = new CLQuery( 86 CLQ_Cert, 87 CertField, 88 numMatches, 89 false, // isFromCache 90 cachedCert->handle()); 91 queryMap.addEntry(*query, query->handle()); 92 93 /* success - copy field data to outgoing Value */ 94 Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); 95 *Value = aData.release(); 96 NumberOfMatchedFields = numMatches; 97 return query->handle(); 98} 99 100 101bool 102AppleX509CLSession::CertGetNextFieldValue( 103 CSSM_HANDLE ResultsHandle, 104 CSSM_DATA_PTR &Value) 105{ 106 /* fetch & validate the query */ 107 CLQuery *query = queryMap.lookupEntry(ResultsHandle); 108 if(query == NULL) { 109 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); 110 } 111 if(query->queryType() != CLQ_Cert) { 112 clErrorLog("CertGetNextFieldValue: bad queryType (%d)", (int)query->queryType()); 113 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); 114 } 115 if(query->nextIndex() >= query->numFields()) { 116 return false; 117 } 118 119 /* fetch the associated cached cert */ 120 CLCachedCert *cachedCert = lookupCachedCert(query->cachedObject()); 121 uint32 dummy; 122 CssmAutoData aData(*this); 123 if(!cachedCert->cert().getCertFieldData(query->fieldId(), 124 query->nextIndex(), 125 dummy, 126 aData)) { 127 return false; 128 } 129 130 /* success - copy field data to outgoing Value */ 131 Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); 132 *Value = aData.release(); 133 query->incrementIndex(); 134 return true; 135} 136 137void 138AppleX509CLSession::CertCache( 139 const CssmData &EncodedCert, 140 CSSM_HANDLE &CertHandle) 141{ 142 DecodedCert *decodedCert = new DecodedCert(*this, EncodedCert); 143 144 /* cook up a CLCachedCert, stash it in cache */ 145 CLCachedCert *cachedCert = new CLCachedCert(*decodedCert); 146 cacheMap.addEntry(*cachedCert, cachedCert->handle()); 147 CertHandle = cachedCert->handle(); 148} 149 150CSSM_HANDLE 151AppleX509CLSession::CertGetFirstCachedFieldValue( 152 CSSM_HANDLE CertHandle, 153 const CssmData &CertField, 154 uint32 &NumberOfMatchedFields, 155 CSSM_DATA_PTR &Value) 156{ 157 /* fetch the associated cached cert */ 158 CLCachedCert *cachedCert = lookupCachedCert(CertHandle); 159 if(cachedCert == NULL) { 160 CssmError::throwMe(CSSMERR_CL_INVALID_CACHE_HANDLE); 161 } 162 163 CssmAutoData aData(*this); 164 uint32 numMatches; 165 166 /* this returns false if field not there, throws on bad OID */ 167 if(!cachedCert->cert().getCertFieldData(CertField, 168 0, // index 169 numMatches, 170 aData)) { 171 return CSSM_INVALID_HANDLE; 172 } 173 174 /* cook up a CLQuery, stash it */ 175 CLQuery *query = new CLQuery( 176 CLQ_Cert, 177 CertField, 178 numMatches, 179 true, // isFromCache 180 cachedCert->handle()); 181 queryMap.addEntry(*query, query->handle()); 182 183 /* success - copy field data to outgoing Value */ 184 Value = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); 185 *Value = aData.release(); 186 NumberOfMatchedFields = numMatches; 187 return query->handle(); 188} 189 190 191bool 192AppleX509CLSession::CertGetNextCachedFieldValue( 193 CSSM_HANDLE ResultsHandle, 194 CSSM_DATA_PTR &Value) 195{ 196 /* Identical to, so just call... */ 197 return CertGetNextFieldValue(ResultsHandle, Value); 198} 199 200void 201AppleX509CLSession::CertAbortCache( 202 CSSM_HANDLE CertHandle) 203{ 204 /* fetch the associated cached cert, remove from map, delete it */ 205 CLCachedCert *cachedCert = lookupCachedCert(CertHandle); 206 if(cachedCert == NULL) { 207 clErrorLog("CertAbortCache: cachedCert not found"); 208 CssmError::throwMe(CSSMERR_CL_INVALID_CACHE_HANDLE); 209 } 210 cacheMap.removeEntry(cachedCert->handle()); 211 delete cachedCert; 212} 213 214/* 215 * Abort either type of cert field query (cache based or non-cache based) 216 */ 217void 218AppleX509CLSession::CertAbortQuery( 219 CSSM_HANDLE ResultsHandle) 220{ 221 /* fetch & validate the query */ 222 CLQuery *query = queryMap.lookupEntry(ResultsHandle); 223 if(query == NULL) { 224 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); 225 } 226 if(query->queryType() != CLQ_Cert) { 227 clErrorLog("CertAbortQuery: bad queryType (%d)", (int)query->queryType()); 228 CssmError::throwMe(CSSMERR_CL_INVALID_RESULTS_HANDLE); 229 } 230 231 if(!query->fromCache()) { 232 /* the associated cached cert was created just for this query; dispose */ 233 CLCachedCert *cachedCert = lookupCachedCert(query->cachedObject()); 234 if(cachedCert == NULL) { 235 /* should never happen */ 236 clErrorLog("CertAbortQuery: cachedCert not found"); 237 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR); 238 } 239 cacheMap.removeEntry(cachedCert->handle()); 240 delete cachedCert; 241 } 242 queryMap.removeEntry(query->handle()); 243 delete query; 244} 245 246void 247AppleX509CLSession::CertCreateTemplate( 248 uint32 NumberOfFields, 249 const CSSM_FIELD CertFields[], 250 CssmData &CertTemplate) 251{ 252 /* cook up an empty Cert */ 253 DecodedCert cert(*this); 254 255 /* grind thru specified fields; exceptions are fatal */ 256 for(uint32 dex=0; dex<NumberOfFields; dex++) { 257 cert.setCertField( 258 CssmOid::overlay(CertFields[dex].FieldOid), 259 CssmData::overlay(CertFields[dex].FieldValue)); 260 } 261 262 /* TBD - ensure all required fields are set? We do this 263 * when we sign the cert; maybe we should do it here. */ 264 265 /* 266 * We have the CertificateToSign in NSS format. Encode. 267 */ 268 CertTemplate.Data = NULL; 269 CertTemplate.Length = 0; 270 CssmRemoteData rData(*this, CertTemplate); 271 cert.encodeTbs(rData); 272 rData.release(); 273} 274 275 276void 277AppleX509CLSession::CertGetAllTemplateFields( 278 const CssmData &CertTemplate, 279 uint32 &NumberOfFields, 280 CSSM_FIELD_PTR &CertFields) 281{ 282 DecodedCert cert(*this); // empty 283 cert.decodeTbs(CertTemplate); 284 cert.getAllParsedCertFields(NumberOfFields, CertFields); 285} 286 287void 288AppleX509CLSession::FreeFields( 289 uint32 NumberOfFields, 290 CSSM_FIELD_PTR &FieldArray) 291{ 292 unsigned i; 293 CSSM_FIELD_PTR thisField; 294 CSSM_OID_PTR thisOid; 295 296 for(i=0; i<NumberOfFields; i++) { 297 thisField = &FieldArray[i]; 298 thisOid = &thisField->FieldOid; 299 300 /* oid-specific handling of value */ 301 /* BUG - the CssmRemoteData constructor clears the referent, 302 * iff the referent is a CSSSM_DATA (as opposed to a CssmData). 303 */ 304 CssmData &cData = CssmData::overlay(thisField->FieldValue); 305 CssmRemoteData rData(*this, cData); 306 try { 307 DecodedCert::freeCertFieldData(CssmOid::overlay(*thisOid), rData); 308 } 309 catch(...) { 310 /* CRL field? */ 311 DecodedCrl::freeCrlFieldData(CssmOid::overlay(*thisOid), rData); 312 } 313 /* and the oid itself */ 314 free(thisOid->Data); 315 thisOid->Data = NULL; 316 thisOid->Length = 0; 317 } 318 free(FieldArray); 319} 320 321void 322AppleX509CLSession::FreeFieldValue( 323 const CssmData &CertOrCrlOid, 324 CssmData &Value) 325{ 326 CssmRemoteData cd(*this, Value); 327 try { 328 DecodedCert::freeCertFieldData(CertOrCrlOid, cd); 329 } 330 catch(...) { 331 /* CRL field? */ 332 DecodedCrl::freeCrlFieldData(CertOrCrlOid, cd); 333 } 334 free(&Value); 335} 336 337void 338AppleX509CLSession::CertGroupFromVerifiedBundle( 339 CSSM_CC_HANDLE CCHandle, 340 const CSSM_CERT_BUNDLE &CertBundle, 341 const CssmData *SignerCert, 342 CSSM_CERTGROUP_PTR &CertGroup) 343{ 344 unimplemented(); 345} 346 347void 348AppleX509CLSession::CertGroupToSignedBundle( 349 CSSM_CC_HANDLE CCHandle, 350 const CSSM_CERTGROUP &CertGroupToBundle, 351 const CSSM_CERT_BUNDLE_HEADER *BundleInfo, 352 CssmData &SignedBundle) 353{ 354 unimplemented(); 355} 356 357void 358AppleX509CLSession::PassThrough( 359 CSSM_CC_HANDLE CCHandle, 360 uint32 PassThroughId, 361 const void *InputParams, 362 void **OutputParams) 363{ 364 switch(PassThroughId) { 365 case CSSM_APPLEX509CL_OBTAIN_CSR: 366 { 367 /* 368 * Create a Cert Signing Request (CSR). 369 * Input is a CSSM_APPLE_CL_CSR_REQUEST. 370 * Output is a PEM-encoded CertSigningRequest (NSS type 371 * NSS_SignedCertRequest from pkcs10). 372 */ 373 if(InputParams == NULL) { 374 CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER); 375 } 376 if(OutputParams == NULL) { 377 CssmError::throwMe(CSSMERR_CL_INVALID_OUTPUT_POINTER); 378 } 379 CSSM_APPLE_CL_CSR_REQUEST *csrReq = 380 (CSSM_APPLE_CL_CSR_REQUEST *)InputParams; 381 if((csrReq->subjectNameX509 == NULL) || 382 (csrReq->signatureOid.Data == NULL) || 383 (csrReq->subjectPublicKey == NULL) || 384 (csrReq->subjectPrivateKey == NULL)) { 385 CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER); 386 } 387 CSSM_DATA_PTR csrPtr = NULL; 388 generateCsr(CCHandle, csrReq, csrPtr); 389 *OutputParams = csrPtr; 390 break; 391 } 392 case CSSM_APPLEX509CL_VERIFY_CSR: 393 { 394 /* 395 * Perform signature verify of a CSR. 396 * Input: CSSM_DATA referring to a DER-encoded CSR. 397 * Output: Nothing, throws CSSMERR_CL_VERIFICATION_FAILURE 398 * on failure. 399 */ 400 if(InputParams == NULL) { 401 CssmError::throwMe(CSSMERR_CL_INVALID_INPUT_POINTER); 402 } 403 const CSSM_DATA *csrPtr = (const CSSM_DATA *)InputParams; 404 verifyCsr(csrPtr); 405 break; 406 } 407 default: 408 CssmError::throwMe(CSSMERR_CL_INVALID_PASSTHROUGH_ID); 409 } 410} 411 412