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/oidscert.h>
32 #include <Security/cssmapple.h>
33 #include <Security/cssmerrno.h>
34 #include <Security/debugging.h>
35 #include <Security/cssmapple.h>
38 #define tpCredDebug(args...) debug("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
;
50 top
->RelativeDistinguishedName
=
51 (CSSM_X509_RDN_PTR
)malloc(sizeof(CSSM_X509_RDN
) * numNames
);
52 CSSM_X509_RDN_PTR rdn
;
53 const CSSM_APPLE_TP_NAME_OID
*nameOid
;
55 for(nameDex
=0; nameDex
<numNames
; nameDex
++) {
56 rdn
= &top
->RelativeDistinguishedName
[nameDex
];
57 nameOid
= &nameArray
[nameDex
];
58 rdn
->numberOfPairs
= 1;
59 rdn
->AttributeTypeAndValue
= (CSSM_X509_TYPE_VALUE_PAIR_PTR
)
60 malloc(sizeof(CSSM_X509_TYPE_VALUE_PAIR
));
61 CSSM_X509_TYPE_VALUE_PAIR_PTR atvp
= rdn
->AttributeTypeAndValue
;
62 tpCopyCssmData(*this, nameOid
->oid
, &atvp
->type
);
63 atvp
->valueType
= BER_TAG_PRINTABLE_STRING
;
64 atvp
->value
.Length
= strlen(nameOid
->string
);
65 atvp
->value
.Data
= (uint8
*)malloc(atvp
->value
.Length
);
66 memmove(atvp
->value
.Data
, nameOid
->string
, atvp
->value
.Length
);
71 /* free the CSSM_X509_NAME obtained from buildX509Name */
72 void AppleTPSession::freeX509Name(
79 CSSM_X509_RDN_PTR rdn
;
80 for(nameDex
=0; nameDex
<top
->numberOfRDNs
; nameDex
++) {
81 rdn
= &top
->RelativeDistinguishedName
[nameDex
];
82 if(rdn
->AttributeTypeAndValue
) {
83 for(unsigned aDex
=0; aDex
<rdn
->numberOfPairs
; aDex
++) {
84 CSSM_X509_TYPE_VALUE_PAIR_PTR atvp
=
85 &rdn
->AttributeTypeAndValue
[aDex
];
86 free(atvp
->type
.Data
);
87 free(atvp
->value
.Data
);
89 free(rdn
->AttributeTypeAndValue
);
92 free(top
->RelativeDistinguishedName
);
96 /* Obtain a CSSM_X509_TIME representing "now" plus specified seconds */
99 * Although RFC 2459, *the* spec for X509 certs, allows for not before/after
100 * times to be expressed in ther generalized (4-digit year) or UTC (2-digit year
101 * with implied century rollover), IE 5 on Mac will not accept the generalized
104 #define TP_FOUR_DIGIT_YEAR 0
105 #if TP_FOUR_DIGIT_YEAR
106 #define TP_TIME_FORMAT TIME_GEN
107 #define TP_TIME_TAG BER_TAG_GENERALIZED_TIME
109 #define TP_TIME_FORMAT TIME_UTC
110 #define TP_TIME_TAG BER_TAG_UTC_TIME
111 #endif /* TP_FOUR_DIGIT_YEAR */
113 CSSM_X509_TIME
* AppleTPSession::buildX509Time(
114 unsigned secondsFromNow
)
116 CSSM_X509_TIME
*xtime
= (CSSM_X509_TIME
*)malloc(sizeof(CSSM_X509_TIME
));
117 xtime
->timeType
= TP_TIME_TAG
;
118 char *ts
= (char *)malloc(GENERALIZED_TIME_STRLEN
+ 1);
120 StLock
<Mutex
> _(tpTimeLock());
121 timeAtNowPlus(secondsFromNow
, TP_TIME_FORMAT
, ts
);
123 xtime
->time
.Data
= (uint8
*)ts
;
124 xtime
->time
.Length
= strlen(ts
);
128 /* Free CSSM_X509_TIME obtained in buildX509Time */
129 void AppleTPSession::freeX509Time(
130 CSSM_X509_TIME
*xtime
)
135 free((char *)xtime
->time
.Data
);
140 * Cook up a CSSM_DATA with specified integer, DER style (minimum number of
141 * bytes, big-endian).
143 static void intToDER(
146 CssmAllocator
&alloc
)
150 DER_Data
.Data
= (uint8
*)alloc
.malloc(1);
151 DER_Data
.Data
[0] = (unsigned char)(theInt
);
153 else if(theInt
< 0x10000) {
155 DER_Data
.Data
= (uint8
*)alloc
.malloc(2);
156 DER_Data
.Data
[0] = (unsigned char)(theInt
>> 8);
157 DER_Data
.Data
[1] = (unsigned char)(theInt
);
159 else if(theInt
< 0x1000000) {
161 DER_Data
.Data
= (uint8
*)alloc
.malloc(3);
162 DER_Data
.Data
[0] = (unsigned char)(theInt
>> 16);
163 DER_Data
.Data
[1] = (unsigned char)(theInt
>> 8);
164 DER_Data
.Data
[2] = (unsigned char)(theInt
);
168 DER_Data
.Data
= (uint8
*)alloc
.malloc(4);
169 DER_Data
.Data
[0] = (unsigned char)(theInt
>> 24);
170 DER_Data
.Data
[1] = (unsigned char)(theInt
>> 16);
171 DER_Data
.Data
[2] = (unsigned char)(theInt
>> 8);
172 DER_Data
.Data
[3] = (unsigned char)(theInt
);
176 /* The reverse of the above. */
177 static uint32
DERToInt(
178 const CSSM_DATA
&DER_Data
)
181 uint8
*bp
= DER_Data
.Data
;
182 for(unsigned dex
=0; dex
<DER_Data
.Length
; dex
++) {
189 /* Convert a reference key to a raw key. */
190 void AppleTPSession::refKeyToRaw(
191 CSSM_CSP_HANDLE cspHand
,
192 const CSSM_KEY
*refKey
,
193 CSSM_KEY_PTR rawKey
) // RETURNED
195 CSSM_CC_HANDLE ccHand
;
197 CSSM_ACCESS_CREDENTIALS creds
;
199 memset(rawKey
, 0, sizeof(CSSM_KEY
));
200 memset(&creds
, 0, sizeof(CSSM_ACCESS_CREDENTIALS
));
201 crtn
= CSSM_CSP_CreateSymmetricContext(cspHand
,
204 &creds
, // passPhrase
205 NULL
, // wrapping key
207 CSSM_PADDING_NONE
, // Padding
211 tpCredDebug("AppleTPSession::refKeyToRaw: context err");
212 CssmError::throwMe(crtn
);
214 crtn
= CSSM_WrapKey(ccHand
,
217 NULL
, // DescriptiveData
219 if(crtn
!= CSSM_OK
) {
220 tpCredDebug("AppleTPSession::refKeyToRaw: wrapKey err");
221 CssmError::throwMe(crtn
);
223 CSSM_DeleteContext(ccHand
);
228 * Cook up an unsigned cert.
229 * This is just a wrapper for CSSM_CL_CertCreateTemplate().
231 void AppleTPSession::makeCertTemplate(
233 CSSM_CL_HANDLE clHand
,
234 CSSM_CSP_HANDLE cspHand
, // for converting ref to raw key
236 const CSSM_X509_NAME
*issuerName
,
237 const CSSM_X509_NAME
*subjectName
,
238 const CSSM_X509_TIME
*notBefore
,
239 const CSSM_X509_TIME
*notAfter
,
240 const CSSM_KEY
*subjectPubKey
,
241 const CSSM_OID
&sigOid
, // e.g., CSSMOID_SHA1WithRSA
243 const CSSM_DATA
*subjectUniqueId
,
244 const CSSM_DATA
*issuerUniqueId
,
245 CSSM_X509_EXTENSION
*extensions
,
246 unsigned numExtensions
,
247 CSSM_DATA_PTR
&rawCert
)
249 CSSM_FIELD
*certTemp
;
250 unsigned fieldDex
= 0; // index into certTemp
251 CSSM_DATA serialDER
= {0, NULL
}; // serial number, DER format
252 CSSM_DATA versionDER
= {0, NULL
};
254 CSSM_X509_ALGORITHM_IDENTIFIER algId
;
255 const CSSM_KEY
*actPubKey
;
257 CSSM_BOOL freeRawKey
= CSSM_FALSE
;
260 algId
.algorithm
= sigOid
;
261 algId
.parameters
.Data
= NULL
;
262 algId
.parameters
.Length
= 0;
265 * Convert possible ref public key to raw format as required by CL.
267 switch(subjectPubKey
->KeyHeader
.BlobType
) {
268 case CSSM_KEYBLOB_RAW
:
269 actPubKey
= subjectPubKey
;
271 case CSSM_KEYBLOB_REFERENCE
:
272 refKeyToRaw(cspHand
, subjectPubKey
, &rawPubKey
);
273 actPubKey
= &rawPubKey
;
274 freeRawKey
= CSSM_TRUE
;
277 tpCredDebug("CSSM_CL_CertCreateTemplate: bad key blob type (%u)",
278 (unsigned)subjectPubKey
->KeyHeader
.BlobType
);
279 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
);
284 * version, always 2 (X509v3)
285 * serialNumber thru subjectPubKey
287 unsigned numFields
= 8 + numExtensions
;
288 if(subjectUniqueId
) {
295 certTemp
= (CSSM_FIELD
*)malloc(sizeof(CSSM_FIELD
) * numFields
);
299 intToDER(2, versionDER
, *this);
300 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1Version
;
301 certTemp
[fieldDex
++].FieldValue
= versionDER
;
304 intToDER(serialNumber
, serialDER
, *this);
305 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1SerialNumber
;
306 certTemp
[fieldDex
++].FieldValue
= serialDER
;
308 /* subject and issuer name */
309 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1IssuerNameCStruct
;
310 certTemp
[fieldDex
].FieldValue
.Data
= (uint8
*)issuerName
;
311 certTemp
[fieldDex
++].FieldValue
.Length
= sizeof(CSSM_X509_NAME
);
313 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1SubjectNameCStruct
;
314 certTemp
[fieldDex
].FieldValue
.Data
= (uint8
*)subjectName
;
315 certTemp
[fieldDex
++].FieldValue
.Length
= sizeof(CSSM_X509_NAME
);
317 /* not before/after */
318 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1ValidityNotBefore
;
319 certTemp
[fieldDex
].FieldValue
.Data
= (uint8
*)notBefore
;
320 certTemp
[fieldDex
++].FieldValue
.Length
= sizeof(CSSM_X509_TIME
);
322 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1ValidityNotAfter
;
323 certTemp
[fieldDex
].FieldValue
.Data
= (uint8
*)notAfter
;
324 certTemp
[fieldDex
++].FieldValue
.Length
= sizeof(CSSM_X509_TIME
);
326 /* the subject key */
327 certTemp
[fieldDex
].FieldOid
= CSSMOID_CSSMKeyStruct
;
328 certTemp
[fieldDex
].FieldValue
.Data
= (uint8
*)actPubKey
;
329 certTemp
[fieldDex
++].FieldValue
.Length
= sizeof(CSSM_KEY
);
331 /* signature algorithm */
332 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1SignatureAlgorithmTBS
;
333 certTemp
[fieldDex
].FieldValue
.Data
= (uint8
*)&algId
;
334 certTemp
[fieldDex
++].FieldValue
.Length
= sizeof(CSSM_X509_ALGORITHM_IDENTIFIER
);
336 /* subject/issuer unique IDs */
337 if(subjectUniqueId
!= 0) {
338 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1CertificateSubjectUniqueId
;
339 certTemp
[fieldDex
++].FieldValue
= *subjectUniqueId
;
341 if(issuerUniqueId
!= 0) {
342 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V1CertificateIssuerUniqueId
;
343 certTemp
[fieldDex
++].FieldValue
= *issuerUniqueId
;
346 for(extNum
=0; extNum
<numExtensions
; extNum
++) {
347 CSSM_X509_EXTENSION_PTR ext
= &extensions
[extNum
];
348 if(ext
->format
== CSSM_X509_DATAFORMAT_PARSED
) {
349 certTemp
[fieldDex
].FieldOid
= ext
->extnId
;
352 certTemp
[fieldDex
].FieldOid
= CSSMOID_X509V3CertificateExtensionCStruct
;
354 certTemp
[fieldDex
].FieldValue
.Data
= (uint8
*)ext
;
355 certTemp
[fieldDex
++].FieldValue
.Length
= sizeof(CSSM_X509_EXTENSION
);
357 assert(fieldDex
== numFields
);
362 rawCert
= (CSSM_DATA_PTR
)malloc(sizeof(CSSM_DATA
));
363 rawCert
->Data
= NULL
;
365 CSSM_RETURN crtn
= CSSM_CL_CertCreateTemplate(clHand
,
370 tpCredDebug("CSSM_CL_CertCreateTemplate returned %s",
371 cssmErrorString(crtn
).c_str());
377 /* free the stuff we mallocd to get here */
378 free(serialDER
.Data
);
379 free(versionDER
.Data
);
382 tpFreeCssmData(*this, &rawPubKey
.KeyData
, CSSM_FALSE
);
385 CssmError::throwMe(crtn
);
389 /* given a cert and a ReferenceIdentifier, fill in ReferenceIdentifier and
390 * add it and the cert to tpCredMap. */
391 void AppleTPSession::addCertToMap(
392 const CSSM_DATA
*cert
,
395 StLock
<Mutex
> _(tpCredMapLock
);
397 TpCredHandle hand
= reinterpret_cast<TpCredHandle
>(cert
);
398 intToDER(hand
, *refId
, *this);
399 tpCredMap
[hand
] = cert
;
402 /* given a ReferenceIdentifier, obtain associated cert and remove from the map */
403 CSSM_DATA_PTR
AppleTPSession::getCertFromMap(
404 const CSSM_DATA
*refId
)
406 StLock
<Mutex
> _(tpCredMapLock
);
407 CSSM_DATA_PTR rtn
= NULL
;
409 if((refId
== NULL
) || (refId
->Data
== NULL
)) {
412 TpCredHandle hand
= DERToInt(*refId
);
413 credMap::iterator it
= tpCredMap
.find(hand
);
414 if(it
== tpCredMap
.end()) {
417 rtn
= const_cast<CSSM_DATA
*>(it
->second
);
418 tpCredMap
.erase(hand
);
423 * SubmitCredRequest, CSR form.
425 void AppleTPSession::SubmitCsrRequest(
426 const CSSM_TP_REQUEST_SET
&RequestInput
,
427 const CSSM_TP_CALLERAUTH_CONTEXT
*CallerAuthContext
,
428 sint32
&EstimatedTime
, // RETURNED
429 CssmData
&ReferenceIdentifier
) // RETURNED
431 CSSM_DATA_PTR csrPtr
= NULL
;
432 CSSM_CC_HANDLE sigHand
= 0;
433 CSSM_APPLE_CL_CSR_REQUEST csrReq
;
435 memset(&csrReq
, 0, sizeof(csrReq
));
437 /* for now we're using the same struct for input as the the normal
438 * X509 cert request. */
439 CSSM_APPLE_TP_CERT_REQUEST
*certReq
=
440 (CSSM_APPLE_TP_CERT_REQUEST
*)RequestInput
.Requests
;
441 if((certReq
->cspHand
== 0) ||
442 (certReq
->clHand
== 0) ||
443 (certReq
->certPublicKey
== NULL
) ||
444 (certReq
->issuerPrivateKey
== NULL
) ||
445 (certReq
->signatureOid
.Data
== NULL
)) {
446 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
);
448 if((certReq
->subjectNames
== NULL
) ||
449 (certReq
->numSubjectNames
== 0)) {
450 CssmError::throwMe(CSSMERR_TP_INVALID_NAME
);
453 /* convert ref public key to raw per CL requirements */
454 const CSSM_KEY
*subjectPubKey
= certReq
->certPublicKey
;
455 const CSSM_KEY
*actPubKey
= NULL
;
456 CSSM_BOOL freeRawKey
= CSSM_FALSE
;
459 switch(subjectPubKey
->KeyHeader
.BlobType
) {
460 case CSSM_KEYBLOB_RAW
:
461 actPubKey
= subjectPubKey
;
463 case CSSM_KEYBLOB_REFERENCE
:
464 refKeyToRaw(certReq
->cspHand
, subjectPubKey
, &rawPubKey
);
465 actPubKey
= &rawPubKey
;
466 freeRawKey
= CSSM_TRUE
;
469 tpCredDebug("SubmitCsrRequest: bad key blob type (%u)",
470 (unsigned)subjectPubKey
->KeyHeader
.BlobType
);
471 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
);
474 /* cook up a CL-passthrough-specific request */
475 csrReq
.subjectNameX509
= buildX509Name(certReq
->subjectNames
,
476 certReq
->numSubjectNames
);
477 csrReq
.signatureAlg
= certReq
->signatureAlg
;
478 csrReq
.signatureOid
= certReq
->signatureOid
;
479 csrReq
.cspHand
= certReq
->cspHand
;
480 csrReq
.subjectPublicKey
= actPubKey
;
481 csrReq
.subjectPrivateKey
= certReq
->issuerPrivateKey
;
482 csrReq
.challengeString
= certReq
->challengeString
;
484 /* A crypto handle to pass to the CL */
486 crtn
= CSSM_CSP_CreateSignatureContext(certReq
->cspHand
,
487 certReq
->signatureAlg
,
488 (CallerAuthContext
? CallerAuthContext
->CallerCredentials
: NULL
),
489 certReq
->issuerPrivateKey
,
492 tpCredDebug("CSSM_CSP_CreateSignatureContext returned %s",
493 cssmErrorString(crtn
).c_str());
497 /* down to the CL to do the actual work */
498 crtn
= CSSM_CL_PassThrough(certReq
->clHand
,
500 CSSM_APPLEX509CL_OBTAIN_CSR
,
504 tpCredDebug("CSSM_CSP_CreateSignatureContext returned %s",
505 cssmErrorString(crtn
).c_str());
509 /* save it for retrieval by RetrieveCredResult */
510 addCertToMap(csrPtr
, &ReferenceIdentifier
);
514 /* free local resources */
515 if(csrReq
.subjectNameX509
) {
516 freeX509Name(csrReq
.subjectNameX509
);
519 CSSM_DeleteContext(sigHand
);
522 tpFreeCssmData(*this, &rawPubKey
.KeyData
, CSSM_FALSE
);
525 CssmError::throwMe(crtn
);
530 * Submit cred (cert) request. Currently the only form of request we
531 * handle is the basis "sign this cert with key right now", with policy OI
532 * CSSMOID_APPLE_TP_LOCAL_CERT_GEN.
534 void AppleTPSession::SubmitCredRequest(
535 const CSSM_TP_AUTHORITY_ID
*PreferredAuthority
,
536 CSSM_TP_AUTHORITY_REQUEST_TYPE RequestType
,
537 const CSSM_TP_REQUEST_SET
&RequestInput
,
538 const CSSM_TP_CALLERAUTH_CONTEXT
*CallerAuthContext
,
539 sint32
&EstimatedTime
,
540 CssmData
&ReferenceIdentifier
)
542 /* free all of these on return if non-NULL */
543 CSSM_DATA_PTR certTemplate
= NULL
;
544 CSSM_X509_TIME_PTR notBeforeX509
= NULL
;
545 CSSM_X509_TIME_PTR notAfterX509
= NULL
;
546 CSSM_X509_NAME_PTR subjectX509
= NULL
;
547 CSSM_X509_NAME_PTR issuerX509
= NULL
;
548 CSSM_X509_EXTENSION_PTR extens509
= NULL
;
549 CSSM_CC_HANDLE sigContext
= 0;
551 /* this gets saved on success */
552 CSSM_DATA_PTR signedCert
= NULL
;
554 /* validate rather limited set of input args */
555 if(PreferredAuthority
!= NULL
) {
556 CssmError::throwMe(CSSMERR_TP_INVALID_AUTHORITY
);
558 if(RequestType
!= CSSM_TP_AUTHORITY_REQUEST_CERTISSUE
) {
559 CssmError::throwMe(CSSMERR_TP_UNSUPPORTED_SERVICE
);
561 if(CallerAuthContext
== NULL
) {
562 CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER
);
564 if((RequestInput
.NumberOfRequests
!= 1) ||
565 (RequestInput
.Requests
== NULL
)) {
566 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
);
569 /* Apple-specific args */
570 const CSSM_TP_POLICYINFO
*tpPolicy
= &CallerAuthContext
->Policy
;
571 if((tpPolicy
->NumberOfPolicyIds
!= 1) ||
572 (tpPolicy
->PolicyIds
== NULL
)) {
573 CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER
);
575 if(tpCompareCssmData(&tpPolicy
->PolicyIds
->FieldOid
,
576 &CSSMOID_APPLE_TP_CSR_GEN
)) {
577 /* break out to CSR-specific code */
578 SubmitCsrRequest(RequestInput
, CallerAuthContext
, EstimatedTime
, ReferenceIdentifier
);
581 else if(!tpCompareCssmData(&tpPolicy
->PolicyIds
->FieldOid
,
582 &CSSMOID_APPLE_TP_LOCAL_CERT_GEN
)) {
583 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
586 CSSM_APPLE_TP_CERT_REQUEST
*certReq
=
587 (CSSM_APPLE_TP_CERT_REQUEST
*)RequestInput
.Requests
;
588 if((certReq
->cspHand
== 0) ||
589 (certReq
->clHand
== 0) ||
590 (certReq
->certPublicKey
== NULL
) ||
591 (certReq
->issuerPrivateKey
== NULL
)) {
592 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
);
594 if((certReq
->subjectNames
== NULL
) ||
595 (certReq
->numSubjectNames
== 0)) {
596 CssmError::throwMe(CSSMERR_TP_INVALID_NAME
);
598 if((certReq
->numExtensions
!= 0) & (certReq
->extensions
== NULL
)) {
599 CssmError::throwMe(CSSMERR_TP_INVALID_POINTER
);
602 CSSM_RETURN ourRtn
= CSSM_OK
;
605 /* convert caller's friendly names and times to CDSA style */
606 subjectX509
= buildX509Name(certReq
->subjectNames
, certReq
->numSubjectNames
);
607 if(certReq
->issuerNames
!= NULL
) {
608 issuerX509
= buildX509Name(certReq
->issuerNames
, certReq
->numIssuerNames
);
610 else if(certReq
->issuerNameX509
) {
611 /* caller obtained this from an existing signer's cert */
612 issuerX509
= certReq
->issuerNameX509
;
616 issuerX509
= subjectX509
;
618 notBeforeX509
= buildX509Time(certReq
->notBefore
);
619 notAfterX509
= buildX509Time(certReq
->notAfter
);
621 if(certReq
->numExtensions
!= 0) {
622 /* convert extensions array from CE_DataAndType to CSSM_X509_EXTENSION */
623 extens509
= (CSSM_X509_EXTENSION
*)malloc(sizeof(CSSM_X509_EXTENSION
) *
624 certReq
->numExtensions
);
625 memset(extens509
, 0, sizeof(CSSM_X509_EXTENSION
) *
626 certReq
->numExtensions
);
627 for(unsigned dex
=0; dex
<certReq
->numExtensions
; dex
++) {
628 CSSM_X509_EXTENSION
*extn
= &extens509
[dex
];
629 CE_DataAndType
*cdt
= &certReq
->extensions
[dex
];
634 case DT_AuthorityKeyID
:
635 parsedValue
= &cdt
->extension
.authorityKeyID
;
636 extnId
= CSSMOID_AuthorityKeyIdentifier
;
638 case DT_SubjectKeyID
:
639 parsedValue
= &cdt
->extension
.subjectKeyID
;
640 extnId
= CSSMOID_SubjectKeyIdentifier
;
643 parsedValue
= &cdt
->extension
.keyUsage
;
644 extnId
= CSSMOID_KeyUsage
;
646 case DT_SubjectAltName
:
647 parsedValue
= &cdt
->extension
.subjectAltName
;
648 extnId
= CSSMOID_SubjectAltName
;
650 case DT_ExtendedKeyUsage
:
651 parsedValue
= &cdt
->extension
.extendedKeyUsage
;
652 extnId
= CSSMOID_ExtendedKeyUsage
;
654 case DT_BasicConstraints
:
655 parsedValue
= &cdt
->extension
.basicConstraints
;
656 extnId
= CSSMOID_BasicConstraints
;
658 case DT_CertPolicies
:
659 parsedValue
= &cdt
->extension
.certPolicies
;
660 extnId
= CSSMOID_CertificatePolicies
;
662 case DT_NetscapeCertType
:
663 parsedValue
= &cdt
->extension
.netscapeCertType
;
664 extnId
= CSSMOID_NetscapeCertType
;
668 tpCredDebug("SubmitCredRequest: DT_Other not supported");
669 CssmError::throwMe(CSSMERR_TP_UNKNOWN_TAG
);
672 extn
->extnId
= extnId
;
673 extn
->critical
= cdt
->critical
;
674 extn
->format
= CSSM_X509_DATAFORMAT_PARSED
;
675 extn
->value
.parsedValue
= parsedValue
;
676 extn
->BERvalue
.Data
= NULL
;
677 extn
->BERvalue
.Length
= 0;
678 } /* for each extension */
679 } /* converting extensions */
681 /* cook up the unsigned template */
682 makeCertTemplate(certReq
->clHand
,
684 certReq
->serialNumber
,
689 certReq
->certPublicKey
,
690 certReq
->signatureOid
,
691 NULL
, // subjectUniqueID, not used here (yet)
692 NULL
, // issuerUniqueId
694 certReq
->numExtensions
,
697 /* create signature context */
698 ourRtn
= CSSM_CSP_CreateSignatureContext(certReq
->cspHand
,
699 certReq
->signatureAlg
,
700 (CallerAuthContext
? CallerAuthContext
->CallerCredentials
: NULL
),
701 certReq
->issuerPrivateKey
,
704 tpCredDebug("CSSM_CSP_CreateSignatureContext returned %s",
705 cssmErrorString(ourRtn
).c_str());
706 CssmError::throwMe(ourRtn
);
709 signedCert
= (CSSM_DATA_PTR
)malloc(sizeof(CSSM_DATA
));
710 signedCert
->Data
= NULL
;
711 signedCert
->Length
= 0;
712 ourRtn
= CSSM_CL_CertSign(certReq
->clHand
,
714 certTemplate
, // CertToBeSigned
719 tpCredDebug("CSSM_CL_CertSign returned %s",
720 cssmErrorString(ourRtn
).c_str());
721 CssmError::throwMe(ourRtn
);
724 /* save it for retrieval by RetrieveCredResult */
725 addCertToMap(signedCert
, &ReferenceIdentifier
);
728 catch (const CssmError
&cerr
) {
729 tpCredDebug("SubmitCredRequest: CSSM error %s",
730 cssmErrorString(cerr
).c_str());
731 ourRtn
= cerr
.cssmError();
734 tpCredDebug("SubmitCredRequest: unknown exception");
735 ourRtn
= CSSMERR_TP_INTERNAL_ERROR
; // ??
739 tpFreeCssmData(*this, certTemplate
, CSSM_TRUE
);
740 freeX509Name(subjectX509
);
741 if(certReq
->issuerNames
) {
742 freeX509Name(issuerX509
);
744 /* else same as subject */
745 freeX509Time(notBeforeX509
);
746 freeX509Time(notAfterX509
);
750 if(sigContext
!= 0) {
751 CSSM_DeleteContext(sigContext
);
754 CssmError::throwMe(ourRtn
);
758 void AppleTPSession::RetrieveCredResult(
759 const CssmData
&ReferenceIdentifier
,
760 const CSSM_TP_CALLERAUTH_CONTEXT
*CallerAuthCredentials
,
761 sint32
&EstimatedTime
,
762 CSSM_BOOL
&ConfirmationRequired
,
763 CSSM_TP_RESULT_SET_PTR
&RetrieveOutput
)
765 const CSSM_DATA
*cert
= getCertFromMap(&ReferenceIdentifier
);
768 tpCredDebug("RetrieveCredResult: refId not found");
769 CssmError::throwMe(CSSMERR_TP_INVALID_IDENTIFIER
);
772 /* CSSM_TP_RESULT_SET.Results points to a CSSM_ENCODED_CERT */
773 CSSM_ENCODED_CERT
*encCert
= (CSSM_ENCODED_CERT
*)malloc(sizeof(CSSM_ENCODED_CERT
));
774 encCert
->CertType
= CSSM_CERT_X_509v3
;
775 encCert
->CertEncoding
= CSSM_CERT_ENCODING_DER
;
778 * caller must free all three:
779 * CSSM_TP_RESULT_SET_PTR RetrieveOutput
780 * RetrieveOutput->Results (CSSM_ENCODED_CERT *encCert)
781 * encCert->CertBlob.Data (the actual cert)
783 encCert
->CertBlob
= *cert
;
784 RetrieveOutput
= (CSSM_TP_RESULT_SET_PTR
)malloc(
785 sizeof(CSSM_TP_RESULT_SET
));
786 RetrieveOutput
->Results
= encCert
;
787 RetrieveOutput
->NumberOfResults
= 1;
788 ConfirmationRequired
= CSSM_FALSE
;