2 * Copyright (c) 2002,2011,2014 Apple 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,
25 #include "AppleTPSession.h"
26 #include "certGroupUtils.h"
27 #include "tpdebugging.h"
29 #include <Security/oidsalg.h>
30 #include <Security/oidsattr.h>
31 #include <Security/oidscert.h>
32 #include <Security/cssmapple.h>
33 #include <security_utilities/debugging.h>
34 #include <Security/cssmapple.h>
35 #include <security_utilities/simulatecrash_assert.h>
37 #define tpCredDebug(args...) secinfo("tpCred", ## args)
40 * Build up a CSSM_X509_NAME from an arbitrary list of name/OID pairs.
41 * We do one a/v pair per RDN.
43 CSSM_X509_NAME
* AppleTPSession::buildX509Name(
44 const CSSM_APPLE_TP_NAME_OID
*nameArray
,
47 CSSM_X509_NAME
*top
= (CSSM_X509_NAME
*)malloc(sizeof(CSSM_X509_NAME
));
48 top
->numberOfRDNs
= numNames
;
51 top
->RelativeDistinguishedName
= NULL
;
54 top
->RelativeDistinguishedName
=
55 (CSSM_X509_RDN_PTR
)malloc(sizeof(CSSM_X509_RDN
) * numNames
);
56 CSSM_X509_RDN_PTR rdn
;
57 const CSSM_APPLE_TP_NAME_OID
*nameOid
;
59 for(nameDex
=0; nameDex
<numNames
; nameDex
++) {
60 rdn
= &top
->RelativeDistinguishedName
[nameDex
];
61 nameOid
= &nameArray
[nameDex
];
62 rdn
->numberOfPairs
= 1;
63 rdn
->AttributeTypeAndValue
= (CSSM_X509_TYPE_VALUE_PAIR_PTR
)
64 malloc(sizeof(CSSM_X509_TYPE_VALUE_PAIR
));
65 CSSM_X509_TYPE_VALUE_PAIR_PTR atvp
= rdn
->AttributeTypeAndValue
;
66 tpCopyCssmData(*this, nameOid
->oid
, &atvp
->type
);
67 atvp
->value
.Length
= strlen(nameOid
->string
);
68 if(tpCompareOids(&CSSMOID_CountryName
, nameOid
->oid
)) {
70 * Country handled differently per RFC 3280 - must be printable,
71 * max of two characters in length
73 if(atvp
->value
.Length
> 2) {
74 CssmError::throwMe(CSSMERR_TP_INVALID_DATA
);
76 for(unsigned dex
=0; dex
<atvp
->value
.Length
; dex
++) {
77 int c
= nameOid
->string
[dex
];
78 if(!isprint(c
) || (c
== EOF
)) {
79 CssmError::throwMe(CSSMERR_TP_INVALID_DATA
);
82 atvp
->valueType
= BER_TAG_PRINTABLE_STRING
;
84 /* other special cases per RFC 3280 */
85 else if(tpCompareOids(&CSSMOID_DNQualifier
, nameOid
->oid
)) {
86 atvp
->valueType
= BER_TAG_PRINTABLE_STRING
;
88 else if(tpCompareOids(&CSSMOID_SerialNumber
, nameOid
->oid
)) {
89 atvp
->valueType
= BER_TAG_PRINTABLE_STRING
;
91 else if(tpCompareOids(&CSSMOID_EmailAddress
, nameOid
->oid
)) {
92 atvp
->valueType
= BER_TAG_IA5_STRING
;
96 atvp
->valueType
= BER_TAG_PKIX_UTF8_STRING
;
98 atvp
->value
.Data
= (uint8
*)malloc(atvp
->value
.Length
);
99 memmove(atvp
->value
.Data
, nameOid
->string
, atvp
->value
.Length
);
104 /* free the CSSM_X509_NAME obtained from buildX509Name */
105 void AppleTPSession::freeX509Name(
112 CSSM_X509_RDN_PTR rdn
;
113 for(nameDex
=0; nameDex
<top
->numberOfRDNs
; nameDex
++) {
114 rdn
= &top
->RelativeDistinguishedName
[nameDex
];
115 if(rdn
->AttributeTypeAndValue
) {
116 for(unsigned aDex
=0; aDex
<rdn
->numberOfPairs
; aDex
++) {
117 CSSM_X509_TYPE_VALUE_PAIR_PTR atvp
=
118 &rdn
->AttributeTypeAndValue
[aDex
];
119 free(atvp
->type
.Data
);
120 free(atvp
->value
.Data
);
122 free(rdn
->AttributeTypeAndValue
);
125 free(top
->RelativeDistinguishedName
);
129 /* Obtain a CSSM_X509_TIME representing "now" plus specified seconds */
132 * Although RFC 2459, *the* spec for X509 certs, allows for not before/after
133 * times to be expressed in ther generalized (4-digit year) or UTC (2-digit year
134 * with implied century rollover), IE 5 on Mac will not accept the generalized
137 #define TP_FOUR_DIGIT_YEAR 0
138 #if TP_FOUR_DIGIT_YEAR
139 #define TP_TIME_FORMAT TP_TIME_GEN
140 #define TP_TIME_TAG BER_TAG_GENERALIZED_TIME
142 #define TP_TIME_FORMAT TP_TIME_UTC
143 #define TP_TIME_TAG BER_TAG_UTC_TIME
144 #endif /* TP_FOUR_DIGIT_YEAR */
146 CSSM_X509_TIME
* AppleTPSession::buildX509Time(
147 unsigned secondsFromNow
)
149 CSSM_X509_TIME
*xtime
= (CSSM_X509_TIME
*)malloc(sizeof(CSSM_X509_TIME
));
150 xtime
->timeType
= TP_TIME_TAG
;
151 char *ts
= (char *)malloc(GENERALIZED_TIME_STRLEN
+ 1);
153 StLock
<Mutex
> _(tpTimeLock());
154 timeAtNowPlus(secondsFromNow
, TP_TIME_FORMAT
, ts
);
156 xtime
->time
.Data
= (uint8
*)ts
;
157 xtime
->time
.Length
= strlen(ts
);
161 /* Free CSSM_X509_TIME obtained in buildX509Time */
162 void AppleTPSession::freeX509Time(
163 CSSM_X509_TIME
*xtime
)
168 free((char *)xtime
->time
.Data
);
173 * Cook up a CSSM_DATA with specified integer, DER style (minimum number of
174 * bytes, big-endian).
176 static void intToDER(
182 * Calculate length in bytes of encoded integer, minimum length of 1.
185 uintptr_t unsignedInt
= (uintptr_t)theInt
;
186 while(unsignedInt
> 0xff) {
192 * DER encoding requires top bit to be zero, else it's a negative number.
193 * Even though we're passing around integers as CSSM_INTPTR, they really are
195 * unsignedInt contains the m.s. byte of theInt in its l.s. byte.
197 if(unsignedInt
& 0x80) {
201 DER_Data
.Data
= (uint8
*)alloc
.malloc(DER_Data
.Length
);
202 uint8
*dst
= DER_Data
.Data
+ DER_Data
.Length
- 1;
203 unsignedInt
= (uintptr_t)theInt
;
204 for(unsigned dex
=0; dex
<DER_Data
.Length
; dex
++) {
205 *dst
-- = unsignedInt
& 0xff;
206 /* this shifts off to zero if we're adding a zero at the top */
211 /* The reverse of the above. */
212 static CSSM_INTPTR
DERToInt(
213 const CSSM_DATA
&DER_Data
)
216 uint8
*bp
= DER_Data
.Data
;
217 for(unsigned dex
=0; dex
<DER_Data
.Length
; dex
++) {
224 /* Convert a reference key to a raw key. */
225 void AppleTPSession::refKeyToRaw(
226 CSSM_CSP_HANDLE cspHand
,
227 const CSSM_KEY
*refKey
,
228 CSSM_KEY_PTR rawKey
) // RETURNED
230 CSSM_CC_HANDLE ccHand
;
232 CSSM_ACCESS_CREDENTIALS creds
;
234 memset(rawKey
, 0, sizeof(CSSM_KEY
));
235 memset(&creds
, 0, sizeof(CSSM_ACCESS_CREDENTIALS
));
236 crtn
= CSSM_CSP_CreateSymmetricContext(cspHand
,
239 &creds
, // passPhrase
240 NULL
, // wrapping key
242 CSSM_PADDING_NONE
, // Padding
246 tpCredDebug("AppleTPSession::refKeyToRaw: context err");
247 CssmError::throwMe(crtn
);
250 crtn
= CSSM_WrapKey(ccHand
,
253 NULL
, // DescriptiveData
255 if(crtn
!= CSSM_OK
) {
256 tpCredDebug("AppleTPSession::refKeyToRaw: wrapKey err");
257 CssmError::throwMe(crtn
);
259 CSSM_DeleteContext(ccHand
);
264 * Cook up an unsigned cert.
265 * This is just a wrapper for CSSM_CL_CertCreateTemplate().
267 void AppleTPSession::makeCertTemplate(
269 CSSM_CL_HANDLE clHand
,
270 CSSM_CSP_HANDLE cspHand
, // for converting ref to raw key
272 const CSSM_X509_NAME
*issuerName
,
273 const CSSM_X509_NAME
*subjectName
,
274 const CSSM_X509_TIME
*notBefore
,
275 const CSSM_X509_TIME
*notAfter
,
276 const CSSM_KEY
*subjectPubKey
,
277 const CSSM_OID
&sigOid
, // e.g., CSSMOID_SHA1WithRSA
279 const CSSM_DATA
*subjectUniqueId
,
280 const CSSM_DATA
*issuerUniqueId
,
281 CSSM_X509_EXTENSION
*extensions
,
282 unsigned numExtensions
,
283 CSSM_DATA_PTR
&rawCert
)
285 CSSM_FIELD
*certTemp
;
286 unsigned fieldDex
= 0; // index into certTemp
287 CSSM_DATA serialDER
= {0, NULL
}; // serial number, DER format
288 CSSM_DATA versionDER
= {0, NULL
};
290 CSSM_X509_ALGORITHM_IDENTIFIER algId
;
291 const CSSM_KEY
*actPubKey
;
293 CSSM_BOOL freeRawKey
= CSSM_FALSE
;
298 * Set Signature Algorithm OID and parameters
300 algId
.algorithm
= sigOid
;
302 /* NULL params - skip for ECDSA */
303 CSSM_ALGORITHMS algorithmType
= 0;
304 cssmOidToAlg(&sigOid
, &algorithmType
);
305 switch(algorithmType
) {
306 case CSSM_ALGID_SHA1WithECDSA
:
307 case CSSM_ALGID_SHA224WithECDSA
:
308 case CSSM_ALGID_SHA256WithECDSA
:
309 case CSSM_ALGID_SHA384WithECDSA
:
310 case CSSM_ALGID_SHA512WithECDSA
:
311 case CSSM_ALGID_ECDSA_SPECIFIED
:
312 algId
.parameters
.Data
= NULL
;
313 algId
.parameters
.Length
= 0;
316 static const uint8 encNull
[2] = { SEC_ASN1_NULL
, 0 };
317 CSSM_DATA encNullData
;
318 encNullData
.Data
= (uint8
*)encNull
;
319 encNullData
.Length
= 2;
321 algId
.parameters
= encNullData
;
327 * Convert possible ref public key to raw format as required by CL.
329 switch(subjectPubKey
->KeyHeader
.BlobType
) {
330 case CSSM_KEYBLOB_RAW
:
331 actPubKey
= subjectPubKey
;
333 case CSSM_KEYBLOB_REFERENCE
:
334 refKeyToRaw(cspHand
, subjectPubKey
, &rawPubKey
);
335 actPubKey
= &rawPubKey
;
336 freeRawKey
= CSSM_TRUE
;
339 tpCredDebug("CSSM_CL_CertCreateTemplate: bad key blob type (%u)",
340 (unsigned)subjectPubKey
->KeyHeader
.BlobType
);
341 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
);
346 * version, always 2 (X509v3)
347 * serialNumber thru subjectPubKey
349 unsigned numFields
= 8 + numExtensions
;
350 if(subjectUniqueId
) {
357 certTemp
= (CSSM_FIELD
*)malloc(sizeof(CSSM_FIELD
) * numFields
);
361 intToDER(2, versionDER
, *this);
362 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1Version
;
363 certTemp
[fieldDex
++].FieldValue
= versionDER
;
366 intToDER(serialNumber
, serialDER
, *this);
367 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1SerialNumber
;
368 certTemp
[fieldDex
++].FieldValue
= serialDER
;
370 /* subject and issuer name */
371 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1IssuerNameCStruct
;
372 certTemp
[fieldDex
].FieldValue
.Data
= (uint8
*)issuerName
;
373 certTemp
[fieldDex
++].FieldValue
.Length
= sizeof(CSSM_X509_NAME
);
375 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1SubjectNameCStruct
;
376 certTemp
[fieldDex
].FieldValue
.Data
= (uint8
*)subjectName
;
377 certTemp
[fieldDex
++].FieldValue
.Length
= sizeof(CSSM_X509_NAME
);
379 /* not before/after */
380 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1ValidityNotBefore
;
381 certTemp
[fieldDex
].FieldValue
.Data
= (uint8
*)notBefore
;
382 certTemp
[fieldDex
++].FieldValue
.Length
= sizeof(CSSM_X509_TIME
);
384 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1ValidityNotAfter
;
385 certTemp
[fieldDex
].FieldValue
.Data
= (uint8
*)notAfter
;
386 certTemp
[fieldDex
++].FieldValue
.Length
= sizeof(CSSM_X509_TIME
);
388 /* the subject key */
389 certTemp
[fieldDex
].FieldOid
= CSSMOID_CSSMKeyStruct
;
390 certTemp
[fieldDex
].FieldValue
.Data
= (uint8
*)actPubKey
;
391 certTemp
[fieldDex
++].FieldValue
.Length
= sizeof(CSSM_KEY
);
393 /* signature algorithm */
394 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1SignatureAlgorithmTBS
;
395 certTemp
[fieldDex
].FieldValue
.Data
= (uint8
*)&algId
;
396 certTemp
[fieldDex
++].FieldValue
.Length
= sizeof(CSSM_X509_ALGORITHM_IDENTIFIER
);
398 /* subject/issuer unique IDs */
399 if(subjectUniqueId
!= 0) {
400 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1CertificateSubjectUniqueId
;
401 certTemp
[fieldDex
++].FieldValue
= *subjectUniqueId
;
403 if(issuerUniqueId
!= 0) {
404 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1CertificateIssuerUniqueId
;
405 certTemp
[fieldDex
++].FieldValue
= *issuerUniqueId
;
408 for(extNum
=0; extNum
<numExtensions
; extNum
++) {
409 CSSM_X509_EXTENSION_PTR ext
= &extensions
[extNum
];
410 if(ext
->format
== CSSM_X509_DATAFORMAT_PARSED
) {
411 certTemp
[fieldDex
].FieldOid
= ext
->extnId
;
414 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V3CertificateExtensionCStruct
;
416 certTemp
[fieldDex
].FieldValue
.Data
= (uint8
*)ext
;
417 certTemp
[fieldDex
++].FieldValue
.Length
= sizeof(CSSM_X509_EXTENSION
);
419 assert(fieldDex
== numFields
);
424 rawCert
= (CSSM_DATA_PTR
)malloc(sizeof(CSSM_DATA
));
425 rawCert
->Data
= NULL
;
427 CSSM_RETURN crtn
= CSSM_CL_CertCreateTemplate(clHand
,
432 tpCredDebug("CSSM_CL_CertCreateTemplate returned %ld", (long)crtn
);
438 /* free the stuff we mallocd to get here */
439 free(serialDER
.Data
);
440 free(versionDER
.Data
);
443 tpFreeCssmData(*this, &rawPubKey
.KeyData
, CSSM_FALSE
);
446 CssmError::throwMe(crtn
);
450 /* given a cert and a ReferenceIdentifier, fill in ReferenceIdentifier and
451 * add it and the cert to tpCredMap. */
452 void AppleTPSession::addCertToMap(
453 const CSSM_DATA
*cert
,
456 StLock
<Mutex
> _(tpCredMapLock
);
458 TpCredHandle hand
= reinterpret_cast<TpCredHandle
>(cert
);
459 intToDER(hand
, *refId
, *this);
460 tpCredMap
[hand
] = cert
;
463 /* given a ReferenceIdentifier, obtain associated cert and remove from the map */
464 CSSM_DATA_PTR
AppleTPSession::getCertFromMap(
465 const CSSM_DATA
*refId
)
467 StLock
<Mutex
> _(tpCredMapLock
);
468 CSSM_DATA_PTR rtn
= NULL
;
470 if((refId
== NULL
) || (refId
->Data
== NULL
)) {
473 TpCredHandle hand
= DERToInt(*refId
);
474 credMap::iterator it
= tpCredMap
.find(hand
);
475 if(it
== tpCredMap
.end()) {
478 rtn
= const_cast<CSSM_DATA
*>(it
->second
);
479 tpCredMap
.erase(hand
);
484 * SubmitCredRequest, CSR form.
486 void AppleTPSession::SubmitCsrRequest(
487 const CSSM_TP_REQUEST_SET
&RequestInput
,
488 const CSSM_TP_CALLERAUTH_CONTEXT
*CallerAuthContext
,
489 sint32
&EstimatedTime
, // RETURNED
490 CssmData
&ReferenceIdentifier
) // RETURNED
492 CSSM_DATA_PTR csrPtr
= NULL
;
493 CSSM_CC_HANDLE sigHand
= 0;
494 CSSM_APPLE_CL_CSR_REQUEST csrReq
;
496 memset(&csrReq
, 0, sizeof(csrReq
));
498 /* for now we're using the same struct for input as the the normal
499 * X509 cert request. */
500 CSSM_APPLE_TP_CERT_REQUEST
*certReq
=
501 (CSSM_APPLE_TP_CERT_REQUEST
*)RequestInput
.Requests
;
502 if((certReq
->cspHand
== 0) ||
503 (certReq
->clHand
== 0) ||
504 (certReq
->certPublicKey
== NULL
) ||
505 (certReq
->issuerPrivateKey
== NULL
) ||
506 (certReq
->signatureOid
.Data
== NULL
)) {
507 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
);
510 /* convert ref public key to raw per CL requirements */
511 const CSSM_KEY
*subjectPubKey
= certReq
->certPublicKey
;
512 const CSSM_KEY
*actPubKey
= NULL
;
513 CSSM_BOOL freeRawKey
= CSSM_FALSE
;
516 switch(subjectPubKey
->KeyHeader
.BlobType
) {
517 case CSSM_KEYBLOB_RAW
:
518 actPubKey
= subjectPubKey
;
520 case CSSM_KEYBLOB_REFERENCE
:
521 refKeyToRaw(certReq
->cspHand
, subjectPubKey
, &rawPubKey
);
522 actPubKey
= &rawPubKey
;
523 freeRawKey
= CSSM_TRUE
;
526 tpCredDebug("SubmitCsrRequest: bad key blob type (%u)",
527 (unsigned)subjectPubKey
->KeyHeader
.BlobType
);
528 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
);
531 /* cook up a CL-passthrough-specific request */
532 csrReq
.subjectNameX509
= buildX509Name(certReq
->subjectNames
,
533 certReq
->numSubjectNames
);
534 csrReq
.signatureAlg
= certReq
->signatureAlg
;
535 csrReq
.signatureOid
= certReq
->signatureOid
;
536 csrReq
.cspHand
= certReq
->cspHand
;
537 csrReq
.subjectPublicKey
= actPubKey
;
538 csrReq
.subjectPrivateKey
= certReq
->issuerPrivateKey
;
539 csrReq
.challengeString
= certReq
->challengeString
;
541 /* A crypto handle to pass to the CL */
543 crtn
= CSSM_CSP_CreateSignatureContext(certReq
->cspHand
,
544 certReq
->signatureAlg
,
545 (CallerAuthContext
? CallerAuthContext
->CallerCredentials
: NULL
),
546 certReq
->issuerPrivateKey
,
549 tpCredDebug("CSSM_CSP_CreateSignatureContext returned %ld", (long)crtn
);
553 /* down to the CL to do the actual work */
554 crtn
= CSSM_CL_PassThrough(certReq
->clHand
,
556 CSSM_APPLEX509CL_OBTAIN_CSR
,
560 tpCredDebug("CSSM_CL_PassThrough returned %ld", (long)crtn
);
564 /* save it for retrieval by RetrieveCredResult */
565 addCertToMap(csrPtr
, &ReferenceIdentifier
);
569 /* free local resources */
570 if(csrReq
.subjectNameX509
) {
571 freeX509Name(csrReq
.subjectNameX509
);
574 CSSM_DeleteContext(sigHand
);
577 tpFreeCssmData(*this, &rawPubKey
.KeyData
, CSSM_FALSE
);
580 CssmError::throwMe(crtn
);
585 * Submit cred (cert) request. Currently the only form of request we
586 * handle is the basis "sign this cert with key right now", with policy OI
587 * CSSMOID_APPLE_TP_LOCAL_CERT_GEN.
589 void AppleTPSession::SubmitCredRequest(
590 const CSSM_TP_AUTHORITY_ID
*PreferredAuthority
,
591 CSSM_TP_AUTHORITY_REQUEST_TYPE RequestType
,
592 const CSSM_TP_REQUEST_SET
&RequestInput
,
593 const CSSM_TP_CALLERAUTH_CONTEXT
*CallerAuthContext
,
594 sint32
&EstimatedTime
,
595 CssmData
&ReferenceIdentifier
)
597 /* free all of these on return if non-NULL */
598 CSSM_DATA_PTR certTemplate
= NULL
;
599 CSSM_X509_TIME_PTR notBeforeX509
= NULL
;
600 CSSM_X509_TIME_PTR notAfterX509
= NULL
;
601 CSSM_X509_NAME_PTR subjectX509
= NULL
;
602 CSSM_X509_NAME_PTR issuerX509
= NULL
;
603 CSSM_X509_EXTENSION_PTR extens509
= NULL
;
604 CSSM_CC_HANDLE sigContext
= 0;
606 /* this gets saved on success */
607 CSSM_DATA_PTR signedCert
= NULL
;
609 /* validate rather limited set of input args */
610 if(PreferredAuthority
!= NULL
) {
611 CssmError::throwMe(CSSMERR_TP_INVALID_AUTHORITY
);
613 if(RequestType
!= CSSM_TP_AUTHORITY_REQUEST_CERTISSUE
) {
614 CssmError::throwMe(CSSMERR_TP_UNSUPPORTED_SERVICE
);
616 if(CallerAuthContext
== NULL
) {
617 CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER
);
619 if((RequestInput
.NumberOfRequests
!= 1) ||
620 (RequestInput
.Requests
== NULL
)) {
621 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
);
624 /* Apple-specific args */
625 const CSSM_TP_POLICYINFO
*tpPolicy
= &CallerAuthContext
->Policy
;
626 if((tpPolicy
->NumberOfPolicyIds
!= 1) ||
627 (tpPolicy
->PolicyIds
== NULL
)) {
628 CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER
);
630 if(tpCompareCssmData(&tpPolicy
->PolicyIds
->FieldOid
,
631 &CSSMOID_APPLE_TP_CSR_GEN
)) {
632 /* break out to CSR-specific code */
633 SubmitCsrRequest(RequestInput
, CallerAuthContext
, EstimatedTime
, ReferenceIdentifier
);
636 else if(!tpCompareCssmData(&tpPolicy
->PolicyIds
->FieldOid
,
637 &CSSMOID_APPLE_TP_LOCAL_CERT_GEN
)) {
638 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
641 CSSM_APPLE_TP_CERT_REQUEST
*certReq
=
642 (CSSM_APPLE_TP_CERT_REQUEST
*)RequestInput
.Requests
;
643 if((certReq
->cspHand
== 0) ||
644 (certReq
->clHand
== 0) ||
645 (certReq
->certPublicKey
== NULL
) ||
646 (certReq
->issuerPrivateKey
== NULL
)) {
647 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
);
649 if((certReq
->numExtensions
!= 0) & (certReq
->extensions
== NULL
)) {
650 CssmError::throwMe(CSSMERR_TP_INVALID_POINTER
);
653 CSSM_RETURN ourRtn
= CSSM_OK
;
656 /* convert caller's friendly names and times to CDSA style */
657 subjectX509
= buildX509Name(certReq
->subjectNames
, certReq
->numSubjectNames
);
658 if(certReq
->issuerNames
!= NULL
) {
659 issuerX509
= buildX509Name(certReq
->issuerNames
, certReq
->numIssuerNames
);
661 else if(certReq
->issuerNameX509
) {
662 /* caller obtained this from an existing signer's cert */
663 issuerX509
= certReq
->issuerNameX509
;
667 issuerX509
= subjectX509
;
669 notBeforeX509
= buildX509Time(certReq
->notBefore
);
670 notAfterX509
= buildX509Time(certReq
->notAfter
);
672 if(certReq
->numExtensions
!= 0) {
673 /* convert extensions array from CE_DataAndType to CSSM_X509_EXTENSION */
674 extens509
= (CSSM_X509_EXTENSION
*)malloc(sizeof(CSSM_X509_EXTENSION
) *
675 certReq
->numExtensions
);
676 memset(extens509
, 0, sizeof(CSSM_X509_EXTENSION
) *
677 certReq
->numExtensions
);
678 for(unsigned dex
=0; dex
<certReq
->numExtensions
; dex
++) {
679 CSSM_X509_EXTENSION
*extn
= &extens509
[dex
];
680 CE_DataAndType
*cdt
= &certReq
->extensions
[dex
];
685 case DT_AuthorityKeyID
:
686 parsedValue
= &cdt
->extension
.authorityKeyID
;
687 extnId
= CSSMOID_AuthorityKeyIdentifier
;
689 case DT_SubjectKeyID
:
690 parsedValue
= &cdt
->extension
.subjectKeyID
;
691 extnId
= CSSMOID_SubjectKeyIdentifier
;
694 parsedValue
= &cdt
->extension
.keyUsage
;
695 extnId
= CSSMOID_KeyUsage
;
697 case DT_SubjectAltName
:
698 parsedValue
= &cdt
->extension
.subjectAltName
;
699 extnId
= CSSMOID_SubjectAltName
;
701 case DT_IssuerAltName
:
702 parsedValue
= &cdt
->extension
.issuerAltName
;
703 extnId
= CSSMOID_IssuerAltName
;
705 case DT_ExtendedKeyUsage
:
706 parsedValue
= &cdt
->extension
.extendedKeyUsage
;
707 extnId
= CSSMOID_ExtendedKeyUsage
;
709 case DT_BasicConstraints
:
710 parsedValue
= &cdt
->extension
.basicConstraints
;
711 extnId
= CSSMOID_BasicConstraints
;
713 case DT_CertPolicies
:
714 parsedValue
= &cdt
->extension
.certPolicies
;
715 extnId
= CSSMOID_CertificatePolicies
;
717 case DT_NetscapeCertType
:
718 parsedValue
= &cdt
->extension
.netscapeCertType
;
719 extnId
= CSSMOID_NetscapeCertType
;
721 case DT_CrlDistributionPoints
:
722 parsedValue
= &cdt
->extension
.crlDistPoints
;
723 extnId
= CSSMOID_CrlDistributionPoints
;
725 case DT_AuthorityInfoAccess
:
726 parsedValue
= &cdt
->extension
.authorityInfoAccess
;
727 extnId
= CSSMOID_AuthorityInfoAccess
;
731 tpCredDebug("SubmitCredRequest: DT_Other not supported");
732 CssmError::throwMe(CSSMERR_TP_UNKNOWN_TAG
);
735 extn
->extnId
= extnId
;
736 extn
->critical
= cdt
->critical
;
737 extn
->format
= CSSM_X509_DATAFORMAT_PARSED
;
738 extn
->value
.parsedValue
= parsedValue
;
739 extn
->BERvalue
.Data
= NULL
;
740 extn
->BERvalue
.Length
= 0;
741 } /* for each extension */
742 } /* converting extensions */
744 /* cook up the unsigned template */
745 makeCertTemplate(certReq
->clHand
,
747 certReq
->serialNumber
,
752 certReq
->certPublicKey
,
753 certReq
->signatureOid
,
754 NULL
, // subjectUniqueID, not used here (yet)
755 NULL
, // issuerUniqueId
757 certReq
->numExtensions
,
760 /* create signature context */
761 ourRtn
= CSSM_CSP_CreateSignatureContext(certReq
->cspHand
,
762 certReq
->signatureAlg
,
763 (CallerAuthContext
? CallerAuthContext
->CallerCredentials
: NULL
),
764 certReq
->issuerPrivateKey
,
767 tpCredDebug("CSSM_CSP_CreateSignatureContext returned %ld", (long)ourRtn
);
768 CssmError::throwMe(ourRtn
);
771 signedCert
= (CSSM_DATA_PTR
)malloc(sizeof(CSSM_DATA
));
772 signedCert
->Data
= NULL
;
773 signedCert
->Length
= 0;
774 ourRtn
= CSSM_CL_CertSign(certReq
->clHand
,
776 certTemplate
, // CertToBeSigned
781 tpCredDebug("CSSM_CL_CertSign returned %ld", (long)ourRtn
);
782 CssmError::throwMe(ourRtn
);
785 /* save it for retrieval by RetrieveCredResult */
786 addCertToMap(signedCert
, &ReferenceIdentifier
);
789 catch (const CssmError
&cerr
) {
790 tpCredDebug("SubmitCredRequest: CSSM error %ld", (long)cerr
.error
);
794 tpCredDebug("SubmitCredRequest: unknown exception");
795 ourRtn
= CSSMERR_TP_INTERNAL_ERROR
; // ??
799 tpFreeCssmData(*this, certTemplate
, CSSM_TRUE
);
800 freeX509Name(subjectX509
);
801 if(certReq
->issuerNames
) {
802 freeX509Name(issuerX509
);
804 /* else same as subject */
805 freeX509Time(notBeforeX509
);
806 freeX509Time(notAfterX509
);
810 if(sigContext
!= 0) {
811 CSSM_DeleteContext(sigContext
);
814 CssmError::throwMe(ourRtn
);
818 void AppleTPSession::RetrieveCredResult(
819 const CssmData
&ReferenceIdentifier
,
820 const CSSM_TP_CALLERAUTH_CONTEXT
*CallerAuthCredentials
,
821 sint32
&EstimatedTime
,
822 CSSM_BOOL
&ConfirmationRequired
,
823 CSSM_TP_RESULT_SET_PTR
&RetrieveOutput
)
825 CSSM_DATA
*cert
= getCertFromMap(&ReferenceIdentifier
);
828 tpCredDebug("RetrieveCredResult: refId not found");
829 CssmError::throwMe(CSSMERR_TP_INVALID_IDENTIFIER
);
832 /* CSSM_TP_RESULT_SET.Results points to a CSSM_ENCODED_CERT */
833 CSSM_ENCODED_CERT
*encCert
= (CSSM_ENCODED_CERT
*)malloc(sizeof(CSSM_ENCODED_CERT
));
834 encCert
->CertType
= CSSM_CERT_X_509v3
;
835 encCert
->CertEncoding
= CSSM_CERT_ENCODING_DER
;
838 * caller must free all three:
839 * CSSM_TP_RESULT_SET_PTR RetrieveOutput
840 * RetrieveOutput->Results (CSSM_ENCODED_CERT *encCert)
841 * encCert->CertBlob.Data (the actual cert)
843 * cert -- mallocd in SubmitCredRequest
845 encCert
->CertBlob
= *cert
;
846 RetrieveOutput
= (CSSM_TP_RESULT_SET_PTR
)malloc(
847 sizeof(CSSM_TP_RESULT_SET
));
848 RetrieveOutput
->Results
= encCert
;
849 RetrieveOutput
->NumberOfResults
= 1;
850 ConfirmationRequired
= CSSM_FALSE
;