2  * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved. 
   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 
  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. 
  20  * tpCredRequest.cpp - credential request functions SubmitCredRequest,  
  23  * Created 1/24/2002 by Doug Mitchell. 
  26 #include "AppleTPSession.h" 
  27 #include "certGroupUtils.h" 
  28 #include "tpdebugging.h" 
  30 #include <Security/oidsalg.h> 
  31 #include <Security/oidsattr.h> 
  32 #include <Security/oidscert.h> 
  33 #include <Security/cssmapple.h> 
  34 #include <security_utilities/debugging.h> 
  35 #include <Security/cssmapple.h> 
  38 #define tpCredDebug(args...)    secdebug("tpCred", ## args) 
  41  * Build up a CSSM_X509_NAME from an arbitrary list of name/OID pairs.  
  42  * We do one a/v pair per RDN.  
  44 CSSM_X509_NAME 
* AppleTPSession::buildX509Name( 
  45         const CSSM_APPLE_TP_NAME_OID 
*nameArray
, 
  48         CSSM_X509_NAME 
*top 
= (CSSM_X509_NAME 
*)malloc(sizeof(CSSM_X509_NAME
)); 
  49         top
->numberOfRDNs 
= numNames
; 
  52                 top
->RelativeDistinguishedName 
= NULL
; 
  55         top
->RelativeDistinguishedName 
=  
  56                 (CSSM_X509_RDN_PTR
)malloc(sizeof(CSSM_X509_RDN
) * numNames
); 
  57         CSSM_X509_RDN_PTR rdn
; 
  58         const CSSM_APPLE_TP_NAME_OID 
*nameOid
; 
  60         for(nameDex
=0; nameDex
<numNames
; nameDex
++) { 
  61                 rdn 
= &top
->RelativeDistinguishedName
[nameDex
]; 
  62                 nameOid 
= &nameArray
[nameDex
]; 
  63                 rdn
->numberOfPairs 
= 1; 
  64                 rdn
->AttributeTypeAndValue 
= (CSSM_X509_TYPE_VALUE_PAIR_PTR
) 
  65                         malloc(sizeof(CSSM_X509_TYPE_VALUE_PAIR
)); 
  66                 CSSM_X509_TYPE_VALUE_PAIR_PTR atvp 
= rdn
->AttributeTypeAndValue
; 
  67                 tpCopyCssmData(*this, nameOid
->oid
, &atvp
->type
); 
  68                 atvp
->value
.Length 
= strlen(nameOid
->string
); 
  69                 if(tpCompareOids(&CSSMOID_CountryName
, nameOid
->oid
)) { 
  71                          * Country handled differently per RFC 3280 - must be printable, 
  72                          * max of two characters in length 
  74                         if(atvp
->value
.Length 
> 2) { 
  75                                 CssmError::throwMe(CSSMERR_TP_INVALID_DATA
); 
  77                         for(unsigned dex
=0; dex
<atvp
->value
.Length
; dex
++) { 
  78                                 int c 
= nameOid
->string
[dex
]; 
  79                                 if(!isprint(c
) || (c 
== EOF
)) { 
  80                                         CssmError::throwMe(CSSMERR_TP_INVALID_DATA
); 
  83                         atvp
->valueType 
= BER_TAG_PRINTABLE_STRING
; 
  85                 /* other special cases per RFC 3280 */ 
  86                 else if(tpCompareOids(&CSSMOID_DNQualifier
, nameOid
->oid
)) { 
  87                         atvp
->valueType 
= BER_TAG_PRINTABLE_STRING
; 
  89                 else if(tpCompareOids(&CSSMOID_SerialNumber
, nameOid
->oid
)) { 
  90                         atvp
->valueType 
= BER_TAG_PRINTABLE_STRING
; 
  92                 else if(tpCompareOids(&CSSMOID_EmailAddress
, nameOid
->oid
)) { 
  93                         atvp
->valueType 
= BER_TAG_IA5_STRING
; 
  97                         atvp
->valueType 
= BER_TAG_PKIX_UTF8_STRING
; 
  99                 atvp
->value
.Data 
= (uint8 
*)malloc(atvp
->value
.Length
); 
 100                 memmove(atvp
->value
.Data
, nameOid
->string
, atvp
->value
.Length
); 
 105 /* free the CSSM_X509_NAME obtained from buildX509Name */ 
 106 void AppleTPSession::freeX509Name( 
 113         CSSM_X509_RDN_PTR rdn
; 
 114         for(nameDex
=0; nameDex
<top
->numberOfRDNs
; nameDex
++) { 
 115                 rdn 
= &top
->RelativeDistinguishedName
[nameDex
]; 
 116                 if(rdn
->AttributeTypeAndValue
) { 
 117                         for(unsigned aDex
=0; aDex
<rdn
->numberOfPairs
; aDex
++) { 
 118                                 CSSM_X509_TYPE_VALUE_PAIR_PTR atvp 
=  
 119                                         &rdn
->AttributeTypeAndValue
[aDex
]; 
 120                                 free(atvp
->type
.Data
); 
 121                                 free(atvp
->value
.Data
); 
 123                         free(rdn
->AttributeTypeAndValue
); 
 126         free(top
->RelativeDistinguishedName
); 
 130 /* Obtain a CSSM_X509_TIME representing "now" plus specified seconds */ 
 133  * Although RFC 2459, *the* spec for X509 certs, allows for not before/after 
 134  * times to be expressed in ther generalized (4-digit year) or UTC (2-digit year 
 135  * with implied century rollover), IE 5 on Mac will not accept the generalized 
 138 #define TP_FOUR_DIGIT_YEAR              0 
 139 #if             TP_FOUR_DIGIT_YEAR 
 140 #define TP_TIME_FORMAT  TIME_GEN 
 141 #define TP_TIME_TAG             BER_TAG_GENERALIZED_TIME 
 143 #define TP_TIME_FORMAT  TIME_UTC 
 144 #define TP_TIME_TAG             BER_TAG_UTC_TIME 
 145 #endif  /* TP_FOUR_DIGIT_YEAR */ 
 147 CSSM_X509_TIME 
* AppleTPSession::buildX509Time( 
 148         unsigned secondsFromNow
) 
 150         CSSM_X509_TIME 
*xtime 
= (CSSM_X509_TIME 
*)malloc(sizeof(CSSM_X509_TIME
)); 
 151         xtime
->timeType 
= TP_TIME_TAG
; 
 152         char *ts 
= (char *)malloc(GENERALIZED_TIME_STRLEN 
+ 1); 
 154                 StLock
<Mutex
> _(tpTimeLock()); 
 155                 timeAtNowPlus(secondsFromNow
, TP_TIME_FORMAT
, ts
); 
 157         xtime
->time
.Data 
= (uint8 
*)ts
; 
 158         xtime
->time
.Length 
= strlen(ts
); 
 162 /* Free CSSM_X509_TIME obtained in buildX509Time */ 
 163 void AppleTPSession::freeX509Time( 
 164         CSSM_X509_TIME  
*xtime
) 
 169         free((char *)xtime
->time
.Data
); 
 174  * Cook up a CSSM_DATA with specified integer, DER style (minimum number of 
 175  * bytes, big-endian). 
 177 static void intToDER( 
 183          * Calculate length in bytes of encoded integer, minimum length of 1.  
 186         uintptr_t unsignedInt 
= (uintptr_t)theInt
; 
 187         while(unsignedInt 
> 0xff) { 
 193          * DER encoding requires top bit to be zero, else it's a negative number.  
 194          * Even though we're passing around integers as CSSM_INTPTR, they really are 
 196          * unsignedInt contains the m.s. byte of theInt in its l.s. byte.  
 198         if(unsignedInt 
& 0x80) { 
 202         DER_Data
.Data 
= (uint8 
*)alloc
.malloc(DER_Data
.Length
); 
 203         uint8 
*dst 
= DER_Data
.Data 
+ DER_Data
.Length 
- 1; 
 204         unsignedInt 
= (uintptr_t)theInt
; 
 205         for(unsigned dex
=0; dex
<DER_Data
.Length
; dex
++) { 
 206                 *dst
-- = unsignedInt 
& 0xff; 
 207                 /* this shifts off to zero if we're adding a zero at the top */ 
 212 /* The reverse of the above. */ 
 213 static CSSM_INTPTR 
DERToInt( 
 214         const CSSM_DATA 
&DER_Data
) 
 217         uint8 
*bp 
= DER_Data
.Data
; 
 218         for(unsigned dex
=0; dex
<DER_Data
.Length
; dex
++) { 
 225 /* Convert a reference key to a raw key. */ 
 226 void AppleTPSession::refKeyToRaw( 
 227         CSSM_CSP_HANDLE cspHand
, 
 228         const CSSM_KEY  
*refKey
,         
 229         CSSM_KEY_PTR    rawKey
)                 // RETURNED 
 231         CSSM_CC_HANDLE          ccHand
; 
 233         CSSM_ACCESS_CREDENTIALS creds
; 
 235         memset(rawKey
, 0, sizeof(CSSM_KEY
)); 
 236         memset(&creds
, 0, sizeof(CSSM_ACCESS_CREDENTIALS
)); 
 237         crtn 
= CSSM_CSP_CreateSymmetricContext(cspHand
, 
 240                         &creds
,                         // passPhrase 
 241                         NULL
,                           // wrapping key 
 243                         CSSM_PADDING_NONE
,      // Padding 
 247                 tpCredDebug("AppleTPSession::refKeyToRaw: context err"); 
 248                 CssmError::throwMe(crtn
); 
 251         crtn 
= CSSM_WrapKey(ccHand
, 
 254                 NULL
,                   // DescriptiveData 
 256         if(crtn 
!= CSSM_OK
) { 
 257                 tpCredDebug("AppleTPSession::refKeyToRaw: wrapKey err"); 
 258                 CssmError::throwMe(crtn
); 
 260         CSSM_DeleteContext(ccHand
); 
 265  * Cook up an unsigned cert. 
 266  * This is just a wrapper for CSSM_CL_CertCreateTemplate(). 
 268 void AppleTPSession::makeCertTemplate( 
 270         CSSM_CL_HANDLE                  clHand
, 
 271         CSSM_CSP_HANDLE                 cspHand
,                // for converting ref to raw key 
 273         const CSSM_X509_NAME    
*issuerName
,     
 274         const CSSM_X509_NAME    
*subjectName
, 
 275         const CSSM_X509_TIME    
*notBefore
,      
 276         const CSSM_X509_TIME    
*notAfter
,       
 277         const CSSM_KEY                  
*subjectPubKey
, 
 278         const CSSM_OID                  
&sigOid
,                // e.g., CSSMOID_SHA1WithRSA 
 280         const CSSM_DATA                 
*subjectUniqueId
, 
 281         const CSSM_DATA                 
*issuerUniqueId
, 
 282         CSSM_X509_EXTENSION             
*extensions
, 
 283         unsigned                                numExtensions
, 
 284         CSSM_DATA_PTR                   
&rawCert
) 
 286         CSSM_FIELD              
*certTemp
;               
 287         unsigned                fieldDex 
= 0;                   // index into certTemp 
 288         CSSM_DATA               serialDER 
= {0, NULL
};  // serial number, DER format 
 289         CSSM_DATA               versionDER 
= {0, NULL
}; 
 291         CSSM_X509_ALGORITHM_IDENTIFIER algId
; 
 292         const CSSM_KEY  
*actPubKey
; 
 294         CSSM_BOOL               freeRawKey 
= CSSM_FALSE
; 
 297         algId
.algorithm 
= sigOid
; 
 298         algId
.parameters
.Data 
= NULL
; 
 299         algId
.parameters
.Length 
= 0; 
 302          * Convert possible ref public key to raw format as required by CL. 
 304         switch(subjectPubKey
->KeyHeader
.BlobType
) { 
 305                 case CSSM_KEYBLOB_RAW
: 
 306                         actPubKey 
= subjectPubKey
; 
 308                 case CSSM_KEYBLOB_REFERENCE
: 
 309                         refKeyToRaw(cspHand
, subjectPubKey
, &rawPubKey
); 
 310                         actPubKey 
= &rawPubKey
; 
 311                         freeRawKey 
= CSSM_TRUE
; 
 314                         tpCredDebug("CSSM_CL_CertCreateTemplate: bad key blob type (%u)", 
 315                                 (unsigned)subjectPubKey
->KeyHeader
.BlobType
); 
 316                         CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
); 
 321          * version, always 2 (X509v3) 
 322          * serialNumber thru subjectPubKey 
 324         unsigned numFields 
= 8 + numExtensions
; 
 325         if(subjectUniqueId
) { 
 332         certTemp 
= (CSSM_FIELD 
*)malloc(sizeof(CSSM_FIELD
) * numFields
); 
 336         intToDER(2, versionDER
, *this); 
 337         certTemp
[fieldDex
].FieldOid 
= CSSMOID_X509V1Version
; 
 338         certTemp
[fieldDex
++].FieldValue 
= versionDER
; 
 341         intToDER(serialNumber
, serialDER
, *this); 
 342         certTemp
[fieldDex
].FieldOid 
= CSSMOID_X509V1SerialNumber
; 
 343         certTemp
[fieldDex
++].FieldValue 
= serialDER
; 
 345         /* subject and issuer name  */ 
 346         certTemp
[fieldDex
].FieldOid 
= CSSMOID_X509V1IssuerNameCStruct
; 
 347         certTemp
[fieldDex
].FieldValue
.Data 
= (uint8 
*)issuerName
; 
 348         certTemp
[fieldDex
++].FieldValue
.Length 
= sizeof(CSSM_X509_NAME
); 
 350         certTemp
[fieldDex
].FieldOid 
= CSSMOID_X509V1SubjectNameCStruct
; 
 351         certTemp
[fieldDex
].FieldValue
.Data 
= (uint8 
*)subjectName
; 
 352         certTemp
[fieldDex
++].FieldValue
.Length 
= sizeof(CSSM_X509_NAME
); 
 354         /* not before/after */ 
 355         certTemp
[fieldDex
].FieldOid 
= CSSMOID_X509V1ValidityNotBefore
; 
 356         certTemp
[fieldDex
].FieldValue
.Data 
= (uint8 
*)notBefore
; 
 357         certTemp
[fieldDex
++].FieldValue
.Length 
= sizeof(CSSM_X509_TIME
); 
 359         certTemp
[fieldDex
].FieldOid 
= CSSMOID_X509V1ValidityNotAfter
; 
 360         certTemp
[fieldDex
].FieldValue
.Data 
= (uint8 
*)notAfter
; 
 361         certTemp
[fieldDex
++].FieldValue
.Length 
= sizeof(CSSM_X509_TIME
); 
 363         /* the subject key */ 
 364         certTemp
[fieldDex
].FieldOid 
= CSSMOID_CSSMKeyStruct
; 
 365         certTemp
[fieldDex
].FieldValue
.Data 
= (uint8 
*)actPubKey
; 
 366         certTemp
[fieldDex
++].FieldValue
.Length 
= sizeof(CSSM_KEY
); 
 368         /* signature algorithm */ 
 369         certTemp
[fieldDex
].FieldOid 
= CSSMOID_X509V1SignatureAlgorithmTBS
; 
 370         certTemp
[fieldDex
].FieldValue
.Data 
= (uint8 
*)&algId
; 
 371         certTemp
[fieldDex
++].FieldValue
.Length 
= sizeof(CSSM_X509_ALGORITHM_IDENTIFIER
); 
 373         /* subject/issuer unique IDs */ 
 374         if(subjectUniqueId 
!= 0) { 
 375                 certTemp
[fieldDex
].FieldOid 
= CSSMOID_X509V1CertificateSubjectUniqueId
; 
 376                 certTemp
[fieldDex
++].FieldValue 
= *subjectUniqueId
; 
 378         if(issuerUniqueId 
!= 0) { 
 379                 certTemp
[fieldDex
].FieldOid 
= CSSMOID_X509V1CertificateIssuerUniqueId
; 
 380                 certTemp
[fieldDex
++].FieldValue 
= *issuerUniqueId
; 
 383         for(extNum
=0; extNum
<numExtensions
; extNum
++) { 
 384                 CSSM_X509_EXTENSION_PTR ext 
= &extensions
[extNum
]; 
 385                 if(ext
->format 
== CSSM_X509_DATAFORMAT_PARSED
) { 
 386                         certTemp
[fieldDex
].FieldOid 
= ext
->extnId
; 
 389                         certTemp
[fieldDex
].FieldOid 
= CSSMOID_X509V3CertificateExtensionCStruct
; 
 391                 certTemp
[fieldDex
].FieldValue
.Data 
= (uint8 
*)ext
; 
 392                 certTemp
[fieldDex
++].FieldValue
.Length 
= sizeof(CSSM_X509_EXTENSION
); 
 394         assert(fieldDex 
== numFields
); 
 399         rawCert 
= (CSSM_DATA_PTR
)malloc(sizeof(CSSM_DATA
)); 
 400         rawCert
->Data 
= NULL
; 
 402         CSSM_RETURN crtn 
= CSSM_CL_CertCreateTemplate(clHand
, 
 407                 tpCredDebug("CSSM_CL_CertCreateTemplate returned %ld", (long)crtn
); 
 413         /* free the stuff we mallocd to get here */ 
 414         free(serialDER
.Data
); 
 415         free(versionDER
.Data
); 
 418                 tpFreeCssmData(*this, &rawPubKey
.KeyData
, CSSM_FALSE
); 
 421                 CssmError::throwMe(crtn
); 
 425 /* given a cert and a ReferenceIdentifier, fill in ReferenceIdentifier and  
 426  * add it and the cert to tpCredMap. */ 
 427 void AppleTPSession::addCertToMap( 
 428         const CSSM_DATA         
*cert
, 
 431         StLock
<Mutex
> _(tpCredMapLock
); 
 433         TpCredHandle hand 
= reinterpret_cast<TpCredHandle
>(cert
); 
 434         intToDER(hand
, *refId
, *this); 
 435         tpCredMap
[hand
] = cert
; 
 438 /* given a ReferenceIdentifier, obtain associated cert and remove from the map */ 
 439 CSSM_DATA_PTR 
AppleTPSession::getCertFromMap( 
 440         const CSSM_DATA 
*refId
) 
 442         StLock
<Mutex
> _(tpCredMapLock
); 
 443         CSSM_DATA_PTR rtn 
= NULL
; 
 445         if((refId 
== NULL
) || (refId
->Data 
== NULL
)) { 
 448         TpCredHandle hand 
= DERToInt(*refId
); 
 449         credMap::iterator it 
= tpCredMap
.find(hand
); 
 450         if(it 
== tpCredMap
.end()) { 
 453         rtn 
= const_cast<CSSM_DATA 
*>(it
->second
); 
 454         tpCredMap
.erase(hand
); 
 459  * SubmitCredRequest, CSR form. 
 461 void AppleTPSession::SubmitCsrRequest( 
 462         const CSSM_TP_REQUEST_SET 
&RequestInput
, 
 463         const CSSM_TP_CALLERAUTH_CONTEXT 
*CallerAuthContext
, 
 464         sint32 
&EstimatedTime
,                                          // RETURNED 
 465         CssmData 
&ReferenceIdentifier
)                          // RETURNED 
 467         CSSM_DATA_PTR   csrPtr 
= NULL
; 
 468         CSSM_CC_HANDLE  sigHand 
= 0; 
 469         CSSM_APPLE_CL_CSR_REQUEST csrReq
; 
 471         memset(&csrReq
, 0, sizeof(csrReq
)); 
 473         /* for now we're using the same struct for input as the the normal 
 474          * X509 cert request. */ 
 475         CSSM_APPLE_TP_CERT_REQUEST 
*certReq 
= 
 476                 (CSSM_APPLE_TP_CERT_REQUEST 
*)RequestInput
.Requests
; 
 477         if((certReq
->cspHand 
== 0) ||  
 478            (certReq
->clHand 
== 0) || 
 479            (certReq
->certPublicKey 
== NULL
) || 
 480            (certReq
->issuerPrivateKey 
== NULL
) || 
 481            (certReq
->signatureOid
.Data 
== NULL
)) { 
 482                 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
); 
 485         /* convert ref public key to raw per CL requirements */ 
 486         const CSSM_KEY 
*subjectPubKey 
= certReq
->certPublicKey
; 
 487         const CSSM_KEY 
*actPubKey 
= NULL
; 
 488         CSSM_BOOL freeRawKey 
= CSSM_FALSE
; 
 491         switch(subjectPubKey
->KeyHeader
.BlobType
) { 
 492                 case CSSM_KEYBLOB_RAW
: 
 493                         actPubKey 
= subjectPubKey
; 
 495                 case CSSM_KEYBLOB_REFERENCE
: 
 496                         refKeyToRaw(certReq
->cspHand
, subjectPubKey
, &rawPubKey
); 
 497                         actPubKey 
= &rawPubKey
; 
 498                         freeRawKey 
= CSSM_TRUE
; 
 501                         tpCredDebug("SubmitCsrRequest: bad key blob type (%u)", 
 502                                 (unsigned)subjectPubKey
->KeyHeader
.BlobType
); 
 503                         CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
); 
 506         /* cook up a CL-passthrough-specific request */ 
 507         csrReq
.subjectNameX509   
= buildX509Name(certReq
->subjectNames
,  
 508                                                                                         certReq
->numSubjectNames
); 
 509         csrReq
.signatureAlg      
= certReq
->signatureAlg
; 
 510         csrReq
.signatureOid      
= certReq
->signatureOid
; 
 511         csrReq
.cspHand                   
= certReq
->cspHand
; 
 512         csrReq
.subjectPublicKey  
= actPubKey
; 
 513         csrReq
.subjectPrivateKey 
= certReq
->issuerPrivateKey
; 
 514         csrReq
.challengeString   
= certReq
->challengeString
; 
 516         /* A crypto handle to pass to the CL */ 
 518         crtn 
= CSSM_CSP_CreateSignatureContext(certReq
->cspHand
, 
 519                         certReq
->signatureAlg
, 
 520                         (CallerAuthContext 
? CallerAuthContext
->CallerCredentials 
: NULL
), 
 521                         certReq
->issuerPrivateKey
, 
 524                 tpCredDebug("CSSM_CSP_CreateSignatureContext returned %ld", (long)crtn
); 
 528         /* down to the CL to do the actual work */ 
 529         crtn 
= CSSM_CL_PassThrough(certReq
->clHand
, 
 531                 CSSM_APPLEX509CL_OBTAIN_CSR
, 
 535                 tpCredDebug("CSSM_CL_PassThrough returned %ld", (long)crtn
); 
 539         /* save it for retrieval by RetrieveCredResult */ 
 540         addCertToMap(csrPtr
, &ReferenceIdentifier
); 
 544         /* free local resources */ 
 545         if(csrReq
.subjectNameX509
) { 
 546                 freeX509Name(csrReq
.subjectNameX509
); 
 549                 CSSM_DeleteContext(sigHand
); 
 552                 tpFreeCssmData(*this, &rawPubKey
.KeyData
, CSSM_FALSE
); 
 555                 CssmError::throwMe(crtn
); 
 560  * Submit cred (cert) request. Currently the only form of request we 
 561  * handle is the basis "sign this cert with key right now", with policy OI 
 562  * CSSMOID_APPLE_TP_LOCAL_CERT_GEN. 
 564 void AppleTPSession::SubmitCredRequest( 
 565         const CSSM_TP_AUTHORITY_ID 
*PreferredAuthority
, 
 566         CSSM_TP_AUTHORITY_REQUEST_TYPE RequestType
, 
 567         const CSSM_TP_REQUEST_SET 
&RequestInput
, 
 568         const CSSM_TP_CALLERAUTH_CONTEXT 
*CallerAuthContext
, 
 569         sint32 
&EstimatedTime
, 
 570         CssmData 
&ReferenceIdentifier
) 
 572         /* free all of these on return if non-NULL */ 
 573         CSSM_DATA_PTR certTemplate 
= NULL
; 
 574         CSSM_X509_TIME_PTR notBeforeX509 
= NULL
; 
 575         CSSM_X509_TIME_PTR notAfterX509 
= NULL
; 
 576         CSSM_X509_NAME_PTR subjectX509 
= NULL
; 
 577         CSSM_X509_NAME_PTR issuerX509 
= NULL
; 
 578         CSSM_X509_EXTENSION_PTR extens509 
= NULL
; 
 579         CSSM_CC_HANDLE sigContext 
= 0; 
 581         /* this gets saved on success */ 
 582         CSSM_DATA_PTR signedCert 
= NULL
; 
 584         /* validate rather limited set of input args */ 
 585         if(PreferredAuthority 
!= NULL
) { 
 586                 CssmError::throwMe(CSSMERR_TP_INVALID_AUTHORITY
); 
 588         if(RequestType 
!= CSSM_TP_AUTHORITY_REQUEST_CERTISSUE
) { 
 589                 CssmError::throwMe(CSSMERR_TP_UNSUPPORTED_SERVICE
); 
 591         if(CallerAuthContext 
== NULL
) { 
 592                 CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER
); 
 594         if((RequestInput
.NumberOfRequests 
!= 1) || 
 595            (RequestInput
.Requests 
== NULL
)) { 
 596                 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
); 
 599         /* Apple-specific args */ 
 600         const CSSM_TP_POLICYINFO 
*tpPolicy 
= &CallerAuthContext
->Policy
; 
 601         if((tpPolicy
->NumberOfPolicyIds 
!= 1) || 
 602            (tpPolicy
->PolicyIds 
== NULL
)) { 
 603                 CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER
); 
 605         if(tpCompareCssmData(&tpPolicy
->PolicyIds
->FieldOid
, 
 606                 &CSSMOID_APPLE_TP_CSR_GEN
)) { 
 607                 /* break out to CSR-specific code */ 
 608                 SubmitCsrRequest(RequestInput
, CallerAuthContext
, EstimatedTime
, ReferenceIdentifier
); 
 611         else if(!tpCompareCssmData(&tpPolicy
->PolicyIds
->FieldOid
, 
 612                 &CSSMOID_APPLE_TP_LOCAL_CERT_GEN
)) { 
 613                 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
); 
 616         CSSM_APPLE_TP_CERT_REQUEST 
*certReq 
= 
 617                 (CSSM_APPLE_TP_CERT_REQUEST 
*)RequestInput
.Requests
; 
 618         if((certReq
->cspHand 
== 0) ||  
 619            (certReq
->clHand 
== 0) || 
 620            (certReq
->certPublicKey 
== NULL
) || 
 621            (certReq
->issuerPrivateKey 
== NULL
)) { 
 622                 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
); 
 624         if((certReq
->numExtensions 
!= 0) & (certReq
->extensions 
== NULL
)) { 
 625                 CssmError::throwMe(CSSMERR_TP_INVALID_POINTER
); 
 628         CSSM_RETURN ourRtn 
= CSSM_OK
; 
 631                 /* convert caller's friendly names and times to CDSA style */ 
 632                 subjectX509 
= buildX509Name(certReq
->subjectNames
, certReq
->numSubjectNames
); 
 633                 if(certReq
->issuerNames 
!= NULL
) { 
 634                         issuerX509 
= buildX509Name(certReq
->issuerNames
, certReq
->numIssuerNames
); 
 636                 else if(certReq
->issuerNameX509
) { 
 637                         /* caller obtained this from an existing signer's cert */ 
 638                         issuerX509 
= certReq
->issuerNameX509
; 
 642                         issuerX509 
= subjectX509
; 
 644                 notBeforeX509 
= buildX509Time(certReq
->notBefore
); 
 645                 notAfterX509 
= buildX509Time(certReq
->notAfter
); 
 647                 if(certReq
->numExtensions 
!= 0) {  
 648                         /* convert extensions array from CE_DataAndType to CSSM_X509_EXTENSION */ 
 649                         extens509 
= (CSSM_X509_EXTENSION 
*)malloc(sizeof(CSSM_X509_EXTENSION
) *  
 650                                         certReq
->numExtensions
); 
 651                         memset(extens509
, 0, sizeof(CSSM_X509_EXTENSION
) *  
 652                                         certReq
->numExtensions
); 
 653                         for(unsigned dex
=0; dex
<certReq
->numExtensions
; dex
++) { 
 654                                 CSSM_X509_EXTENSION 
*extn 
= &extens509
[dex
]; 
 655                                 CE_DataAndType 
*cdt 
= &certReq
->extensions
[dex
]; 
 660                                         case DT_AuthorityKeyID
:  
 661                                                 parsedValue 
= &cdt
->extension
.authorityKeyID
; 
 662                                                 extnId 
= CSSMOID_AuthorityKeyIdentifier
; 
 664                                         case DT_SubjectKeyID
:            
 665                                                 parsedValue 
= &cdt
->extension
.subjectKeyID
; 
 666                                                 extnId 
= CSSMOID_SubjectKeyIdentifier
; 
 669                                                 parsedValue 
= &cdt
->extension
.keyUsage
; 
 670                                                 extnId 
= CSSMOID_KeyUsage
; 
 672                                         case DT_SubjectAltName
:                  
 673                                                 parsedValue 
= &cdt
->extension
.subjectAltName
; 
 674                                                 extnId 
= CSSMOID_SubjectAltName
; 
 676                                         case DT_IssuerAltName
:                   
 677                                                 parsedValue 
= &cdt
->extension
.issuerAltName
; 
 678                                                 extnId 
= CSSMOID_IssuerAltName
; 
 680                                         case DT_ExtendedKeyUsage
:                
 681                                                 parsedValue 
= &cdt
->extension
.extendedKeyUsage
; 
 682                                                 extnId 
= CSSMOID_ExtendedKeyUsage
; 
 684                                         case DT_BasicConstraints
:                
 685                                                 parsedValue 
= &cdt
->extension
.basicConstraints
; 
 686                                                 extnId 
= CSSMOID_BasicConstraints
; 
 688                                         case DT_CertPolicies
:                    
 689                                                 parsedValue 
= &cdt
->extension
.certPolicies
; 
 690                                                 extnId 
= CSSMOID_CertificatePolicies
; 
 692                                         case DT_NetscapeCertType
:                
 693                                                 parsedValue 
= &cdt
->extension
.netscapeCertType
; 
 694                                                 extnId 
= CSSMOID_NetscapeCertType
; 
 696                                         case DT_CrlDistributionPoints
:           
 697                                                 parsedValue 
= &cdt
->extension
.crlDistPoints
; 
 698                                                 extnId 
= CSSMOID_CrlDistributionPoints
; 
 700                                         case DT_AuthorityInfoAccess
:             
 701                                                 parsedValue 
= &cdt
->extension
.authorityInfoAccess
; 
 702                                                 extnId 
= CSSMOID_AuthorityInfoAccess
; 
 706                                                 tpCredDebug("SubmitCredRequest: DT_Other not supported"); 
 707                                                 CssmError::throwMe(CSSMERR_TP_UNKNOWN_TAG
); 
 710                                 extn
->extnId                    
= extnId
; 
 711                                 extn
->critical                  
= cdt
->critical
; 
 712                                 extn
->format                    
= CSSM_X509_DATAFORMAT_PARSED
; 
 713                                 extn
->value
.parsedValue         
= parsedValue
; 
 714                                 extn
->BERvalue
.Data 
= NULL
; 
 715                                 extn
->BERvalue
.Length 
= 0; 
 716                         }       /* for each extension */ 
 717                 }               /* converting extensions */ 
 719                 /* cook up the unsigned template */ 
 720                 makeCertTemplate(certReq
->clHand
, 
 722                         certReq
->serialNumber
, 
 727                         certReq
->certPublicKey
, 
 728                         certReq
->signatureOid
, 
 729                         NULL
,                           // subjectUniqueID, not used here (yet) 
 730                         NULL
,                           // issuerUniqueId 
 732                         certReq
->numExtensions
, 
 735                 /* create signature context */           
 736                 ourRtn 
= CSSM_CSP_CreateSignatureContext(certReq
->cspHand
, 
 737                                 certReq
->signatureAlg
, 
 738                                 (CallerAuthContext 
? CallerAuthContext
->CallerCredentials 
: NULL
), 
 739                                 certReq
->issuerPrivateKey
, 
 742                         tpCredDebug("CSSM_CSP_CreateSignatureContext returned %ld", (long)ourRtn
); 
 743                         CssmError::throwMe(ourRtn
); 
 746                 signedCert 
= (CSSM_DATA_PTR
)malloc(sizeof(CSSM_DATA
)); 
 747                 signedCert
->Data 
= NULL
; 
 748                 signedCert
->Length 
= 0; 
 749                 ourRtn 
= CSSM_CL_CertSign(certReq
->clHand
, 
 751                         certTemplate
,           // CertToBeSigned 
 756                         tpCredDebug("CSSM_CL_CertSign returned %ld", (long)ourRtn
); 
 757                         CssmError::throwMe(ourRtn
); 
 760                 /* save it for retrieval by RetrieveCredResult */ 
 761                 addCertToMap(signedCert
, &ReferenceIdentifier
); 
 764         catch (const CssmError 
&cerr
) { 
 765                 tpCredDebug("SubmitCredRequest: CSSM error %ld", (long)cerr
.error
); 
 769                 tpCredDebug("SubmitCredRequest: unknown exception"); 
 770                 ourRtn 
= CSSMERR_TP_INTERNAL_ERROR
;     // ?? 
 774         tpFreeCssmData(*this, certTemplate
, CSSM_TRUE
); 
 775         freeX509Name(subjectX509
); 
 776         if(certReq
->issuerNames
) { 
 777                 freeX509Name(issuerX509
); 
 779         /* else same as subject */ 
 780         freeX509Time(notBeforeX509
); 
 781         freeX509Time(notAfterX509
); 
 785         if(sigContext 
!= 0) { 
 786                 CSSM_DeleteContext(sigContext
); 
 789                 CssmError::throwMe(ourRtn
); 
 793 void AppleTPSession::RetrieveCredResult( 
 794         const CssmData 
&ReferenceIdentifier
, 
 795         const CSSM_TP_CALLERAUTH_CONTEXT 
*CallerAuthCredentials
, 
 796         sint32 
&EstimatedTime
, 
 797         CSSM_BOOL 
&ConfirmationRequired
, 
 798         CSSM_TP_RESULT_SET_PTR 
&RetrieveOutput
) 
 800         CSSM_DATA 
*cert 
= getCertFromMap(&ReferenceIdentifier
); 
 803                 tpCredDebug("RetrieveCredResult: refId not found"); 
 804                 CssmError::throwMe(CSSMERR_TP_INVALID_IDENTIFIER
); 
 807         /* CSSM_TP_RESULT_SET.Results points to a CSSM_ENCODED_CERT */ 
 808         CSSM_ENCODED_CERT 
*encCert 
= (CSSM_ENCODED_CERT 
*)malloc(sizeof(CSSM_ENCODED_CERT
)); 
 809         encCert
->CertType 
= CSSM_CERT_X_509v3
; 
 810         encCert
->CertEncoding 
= CSSM_CERT_ENCODING_DER
; 
 813          * caller must free all three: 
 814          *   CSSM_TP_RESULT_SET_PTR RetrieveOutput 
 815          *   RetrieveOutput->Results (CSSM_ENCODED_CERT *encCert) 
 816          *   encCert->CertBlob.Data (the actual cert) 
 818          *       cert                                   -- mallocd in SubmitCredRequest 
 820         encCert
->CertBlob 
= *cert
; 
 821         RetrieveOutput 
= (CSSM_TP_RESULT_SET_PTR
)malloc( 
 822                 sizeof(CSSM_TP_RESULT_SET
)); 
 823         RetrieveOutput
->Results 
= encCert
; 
 824         RetrieveOutput
->NumberOfResults 
= 1; 
 825         ConfirmationRequired 
= CSSM_FALSE
;