+++ /dev/null
-/*
- * Copyright (c) 2002,2011,2014 Apple Inc. All Rights Reserved.
- *
- * The contents of this file constitute Original Code as defined in and are
- * subject to the Apple Public Source License Version 1.2 (the 'License').
- * You may not use this file except in compliance with the License. Please obtain
- * a copy of the License at http://www.apple.com/publicsource and read it before
- * using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
- * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
- * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
- * specific language governing rights and limitations under the License.
- */
-
-
-/*
- * tpCredRequest.cpp - credential request functions SubmitCredRequest,
- * RetrieveCredResult
- *
- */
-
-#include "AppleTPSession.h"
-#include "certGroupUtils.h"
-#include "tpdebugging.h"
-#include "tpTime.h"
-#include <Security/oidsalg.h>
-#include <Security/oidsattr.h>
-#include <Security/oidscert.h>
-#include <Security/cssmapple.h>
-#include <security_utilities/debugging.h>
-#include <Security/cssmapple.h>
-#include <assert.h>
-
-#define tpCredDebug(args...) secdebug("tpCred", ## args)
-
-/*
- * Build up a CSSM_X509_NAME from an arbitrary list of name/OID pairs.
- * We do one a/v pair per RDN.
- */
-CSSM_X509_NAME * AppleTPSession::buildX509Name(
- const CSSM_APPLE_TP_NAME_OID *nameArray,
- unsigned numNames)
-{
- CSSM_X509_NAME *top = (CSSM_X509_NAME *)malloc(sizeof(CSSM_X509_NAME));
- top->numberOfRDNs = numNames;
- if(numNames == 0) {
- /* legal! */
- top->RelativeDistinguishedName = NULL;
- return top;
- }
- top->RelativeDistinguishedName =
- (CSSM_X509_RDN_PTR)malloc(sizeof(CSSM_X509_RDN) * numNames);
- CSSM_X509_RDN_PTR rdn;
- const CSSM_APPLE_TP_NAME_OID *nameOid;
- unsigned nameDex;
- for(nameDex=0; nameDex<numNames; nameDex++) {
- rdn = &top->RelativeDistinguishedName[nameDex];
- nameOid = &nameArray[nameDex];
- rdn->numberOfPairs = 1;
- rdn->AttributeTypeAndValue = (CSSM_X509_TYPE_VALUE_PAIR_PTR)
- malloc(sizeof(CSSM_X509_TYPE_VALUE_PAIR));
- CSSM_X509_TYPE_VALUE_PAIR_PTR atvp = rdn->AttributeTypeAndValue;
- tpCopyCssmData(*this, nameOid->oid, &atvp->type);
- atvp->value.Length = strlen(nameOid->string);
- if(tpCompareOids(&CSSMOID_CountryName, nameOid->oid)) {
- /*
- * Country handled differently per RFC 3280 - must be printable,
- * max of two characters in length
- */
- if(atvp->value.Length > 2) {
- CssmError::throwMe(CSSMERR_TP_INVALID_DATA);
- }
- for(unsigned dex=0; dex<atvp->value.Length; dex++) {
- int c = nameOid->string[dex];
- if(!isprint(c) || (c == EOF)) {
- CssmError::throwMe(CSSMERR_TP_INVALID_DATA);
- }
- }
- atvp->valueType = BER_TAG_PRINTABLE_STRING;
- }
- /* other special cases per RFC 3280 */
- else if(tpCompareOids(&CSSMOID_DNQualifier, nameOid->oid)) {
- atvp->valueType = BER_TAG_PRINTABLE_STRING;
- }
- else if(tpCompareOids(&CSSMOID_SerialNumber, nameOid->oid)) {
- atvp->valueType = BER_TAG_PRINTABLE_STRING;
- }
- else if(tpCompareOids(&CSSMOID_EmailAddress, nameOid->oid)) {
- atvp->valueType = BER_TAG_IA5_STRING;
- }
- else {
- /* Default type */
- atvp->valueType = BER_TAG_PKIX_UTF8_STRING;
- }
- atvp->value.Data = (uint8 *)malloc(atvp->value.Length);
- memmove(atvp->value.Data, nameOid->string, atvp->value.Length);
- }
- return top;
-}
-
-/* free the CSSM_X509_NAME obtained from buildX509Name */
-void AppleTPSession::freeX509Name(
- CSSM_X509_NAME *top)
-{
- if(top == NULL) {
- return;
- }
- unsigned nameDex;
- CSSM_X509_RDN_PTR rdn;
- for(nameDex=0; nameDex<top->numberOfRDNs; nameDex++) {
- rdn = &top->RelativeDistinguishedName[nameDex];
- if(rdn->AttributeTypeAndValue) {
- for(unsigned aDex=0; aDex<rdn->numberOfPairs; aDex++) {
- CSSM_X509_TYPE_VALUE_PAIR_PTR atvp =
- &rdn->AttributeTypeAndValue[aDex];
- free(atvp->type.Data);
- free(atvp->value.Data);
- }
- free(rdn->AttributeTypeAndValue);
- }
- }
- free(top->RelativeDistinguishedName);
- free(top);
-}
-
-/* Obtain a CSSM_X509_TIME representing "now" plus specified seconds */
-
-/*
- * Although RFC 2459, *the* spec for X509 certs, allows for not before/after
- * times to be expressed in ther generalized (4-digit year) or UTC (2-digit year
- * with implied century rollover), IE 5 on Mac will not accept the generalized
- * format.
- */
-#define TP_FOUR_DIGIT_YEAR 0
-#if TP_FOUR_DIGIT_YEAR
-#define TP_TIME_FORMAT TIME_GEN
-#define TP_TIME_TAG BER_TAG_GENERALIZED_TIME
-#else
-#define TP_TIME_FORMAT TIME_UTC
-#define TP_TIME_TAG BER_TAG_UTC_TIME
-#endif /* TP_FOUR_DIGIT_YEAR */
-
-CSSM_X509_TIME * AppleTPSession::buildX509Time(
- unsigned secondsFromNow)
-{
- CSSM_X509_TIME *xtime = (CSSM_X509_TIME *)malloc(sizeof(CSSM_X509_TIME));
- xtime->timeType = TP_TIME_TAG;
- char *ts = (char *)malloc(GENERALIZED_TIME_STRLEN + 1);
- {
- StLock<Mutex> _(tpTimeLock());
- timeAtNowPlus(secondsFromNow, TP_TIME_FORMAT, ts);
- }
- xtime->time.Data = (uint8 *)ts;
- xtime->time.Length = strlen(ts);
- return xtime;
-}
-
-/* Free CSSM_X509_TIME obtained in buildX509Time */
-void AppleTPSession::freeX509Time(
- CSSM_X509_TIME *xtime)
-{
- if(xtime == NULL) {
- return;
- }
- free((char *)xtime->time.Data);
- free(xtime);
-}
-
-/*
- * Cook up a CSSM_DATA with specified integer, DER style (minimum number of
- * bytes, big-endian).
- */
-static void intToDER(
- CSSM_INTPTR theInt,
- CSSM_DATA &DER_Data,
- Allocator &alloc)
-{
- /*
- * Calculate length in bytes of encoded integer, minimum length of 1.
- */
- DER_Data.Length = 1;
- uintptr_t unsignedInt = (uintptr_t)theInt;
- while(unsignedInt > 0xff) {
- DER_Data.Length++;
- unsignedInt >>= 8;
- }
-
- /*
- * DER encoding requires top bit to be zero, else it's a negative number.
- * Even though we're passing around integers as CSSM_INTPTR, they really are
- * always unsigned.
- * unsignedInt contains the m.s. byte of theInt in its l.s. byte.
- */
- if(unsignedInt & 0x80) {
- DER_Data.Length++;
- }
-
- DER_Data.Data = (uint8 *)alloc.malloc(DER_Data.Length);
- uint8 *dst = DER_Data.Data + DER_Data.Length - 1;
- unsignedInt = (uintptr_t)theInt;
- for(unsigned dex=0; dex<DER_Data.Length; dex++) {
- *dst-- = unsignedInt & 0xff;
- /* this shifts off to zero if we're adding a zero at the top */
- unsignedInt >>= 8;
- }
-}
-
-/* The reverse of the above. */
-static CSSM_INTPTR DERToInt(
- const CSSM_DATA &DER_Data)
-{
- CSSM_INTPTR rtn = 0;
- uint8 *bp = DER_Data.Data;
- for(unsigned dex=0; dex<DER_Data.Length; dex++) {
- rtn <<= 8;
- rtn |= *bp++;
- }
- return rtn;
-}
-
-/* Convert a reference key to a raw key. */
-void AppleTPSession::refKeyToRaw(
- CSSM_CSP_HANDLE cspHand,
- const CSSM_KEY *refKey,
- CSSM_KEY_PTR rawKey) // RETURNED
-{
- CSSM_CC_HANDLE ccHand;
- CSSM_RETURN crtn;
- CSSM_ACCESS_CREDENTIALS creds;
-
- memset(rawKey, 0, sizeof(CSSM_KEY));
- memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
- crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
- CSSM_ALGID_NONE,
- CSSM_ALGMODE_NONE,
- &creds, // passPhrase
- NULL, // wrapping key
- NULL, // init vector
- CSSM_PADDING_NONE, // Padding
- 0, // Params
- &ccHand);
- if(crtn) {
- tpCredDebug("AppleTPSession::refKeyToRaw: context err");
- CssmError::throwMe(crtn);
- }
-
- crtn = CSSM_WrapKey(ccHand,
- &creds,
- refKey,
- NULL, // DescriptiveData
- rawKey);
- if(crtn != CSSM_OK) {
- tpCredDebug("AppleTPSession::refKeyToRaw: wrapKey err");
- CssmError::throwMe(crtn);
- }
- CSSM_DeleteContext(ccHand);
-}
-
-
-/*
- * Cook up an unsigned cert.
- * This is just a wrapper for CSSM_CL_CertCreateTemplate().
- */
-void AppleTPSession::makeCertTemplate(
- /* required */
- CSSM_CL_HANDLE clHand,
- CSSM_CSP_HANDLE cspHand, // for converting ref to raw key
- uint32 serialNumber,
- const CSSM_X509_NAME *issuerName,
- const CSSM_X509_NAME *subjectName,
- const CSSM_X509_TIME *notBefore,
- const CSSM_X509_TIME *notAfter,
- const CSSM_KEY *subjectPubKey,
- const CSSM_OID &sigOid, // e.g., CSSMOID_SHA1WithRSA
- /* optional */
- const CSSM_DATA *subjectUniqueId,
- const CSSM_DATA *issuerUniqueId,
- CSSM_X509_EXTENSION *extensions,
- unsigned numExtensions,
- CSSM_DATA_PTR &rawCert)
-{
- CSSM_FIELD *certTemp;
- unsigned fieldDex = 0; // index into certTemp
- CSSM_DATA serialDER = {0, NULL}; // serial number, DER format
- CSSM_DATA versionDER = {0, NULL};
- unsigned extNum;
- CSSM_X509_ALGORITHM_IDENTIFIER algId;
- const CSSM_KEY *actPubKey;
- CSSM_KEY rawPubKey;
- CSSM_BOOL freeRawKey = CSSM_FALSE;
-
- rawCert = NULL;
-
- /*
- * Set Signature Algorithm OID and parameters
- */
- algId.algorithm = sigOid;
-
- /* NULL params - skip for ECDSA */
- CSSM_ALGORITHMS algorithmType = 0;
- cssmOidToAlg(&sigOid, &algorithmType);
- switch(algorithmType) {
- case CSSM_ALGID_SHA1WithECDSA:
- case CSSM_ALGID_SHA224WithECDSA:
- case CSSM_ALGID_SHA256WithECDSA:
- case CSSM_ALGID_SHA384WithECDSA:
- case CSSM_ALGID_SHA512WithECDSA:
- case CSSM_ALGID_ECDSA_SPECIFIED:
- algId.parameters.Data = NULL;
- algId.parameters.Length = 0;
- break;
- default:
- static const uint8 encNull[2] = { SEC_ASN1_NULL, 0 };
- CSSM_DATA encNullData;
- encNullData.Data = (uint8 *)encNull;
- encNullData.Length = 2;
-
- algId.parameters = encNullData;
- break;
- }
-
-
- /*
- * Convert possible ref public key to raw format as required by CL.
- */
- switch(subjectPubKey->KeyHeader.BlobType) {
- case CSSM_KEYBLOB_RAW:
- actPubKey = subjectPubKey;
- break;
- case CSSM_KEYBLOB_REFERENCE:
- refKeyToRaw(cspHand, subjectPubKey, &rawPubKey);
- actPubKey = &rawPubKey;
- freeRawKey = CSSM_TRUE;
- break;
- default:
- tpCredDebug("CSSM_CL_CertCreateTemplate: bad key blob type (%u)",
- (unsigned)subjectPubKey->KeyHeader.BlobType);
- CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS);
- }
-
-
- /*
- * version, always 2 (X509v3)
- * serialNumber thru subjectPubKey
- */
- unsigned numFields = 8 + numExtensions;
- if(subjectUniqueId) {
- numFields++;
- }
- if(issuerUniqueId) {
- numFields++;
- }
-
- certTemp = (CSSM_FIELD *)malloc(sizeof(CSSM_FIELD) * numFields);
-
-
- /* version */
- intToDER(2, versionDER, *this);
- certTemp[fieldDex].FieldOid = CSSMOID_X509V1Version;
- certTemp[fieldDex++].FieldValue = versionDER;
-
- /* serial number */
- intToDER(serialNumber, serialDER, *this);
- certTemp[fieldDex].FieldOid = CSSMOID_X509V1SerialNumber;
- certTemp[fieldDex++].FieldValue = serialDER;
-
- /* subject and issuer name */
- certTemp[fieldDex].FieldOid = CSSMOID_X509V1IssuerNameCStruct;
- certTemp[fieldDex].FieldValue.Data = (uint8 *)issuerName;
- certTemp[fieldDex++].FieldValue.Length = sizeof(CSSM_X509_NAME);
-
- certTemp[fieldDex].FieldOid = CSSMOID_X509V1SubjectNameCStruct;
- certTemp[fieldDex].FieldValue.Data = (uint8 *)subjectName;
- certTemp[fieldDex++].FieldValue.Length = sizeof(CSSM_X509_NAME);
-
- /* not before/after */
- certTemp[fieldDex].FieldOid = CSSMOID_X509V1ValidityNotBefore;
- certTemp[fieldDex].FieldValue.Data = (uint8 *)notBefore;
- certTemp[fieldDex++].FieldValue.Length = sizeof(CSSM_X509_TIME);
-
- certTemp[fieldDex].FieldOid = CSSMOID_X509V1ValidityNotAfter;
- certTemp[fieldDex].FieldValue.Data = (uint8 *)notAfter;
- certTemp[fieldDex++].FieldValue.Length = sizeof(CSSM_X509_TIME);
-
- /* the subject key */
- certTemp[fieldDex].FieldOid = CSSMOID_CSSMKeyStruct;
- certTemp[fieldDex].FieldValue.Data = (uint8 *)actPubKey;
- certTemp[fieldDex++].FieldValue.Length = sizeof(CSSM_KEY);
-
- /* signature algorithm */
- certTemp[fieldDex].FieldOid = CSSMOID_X509V1SignatureAlgorithmTBS;
- certTemp[fieldDex].FieldValue.Data = (uint8 *)&algId;
- certTemp[fieldDex++].FieldValue.Length = sizeof(CSSM_X509_ALGORITHM_IDENTIFIER);
-
- /* subject/issuer unique IDs */
- if(subjectUniqueId != 0) {
- certTemp[fieldDex].FieldOid = CSSMOID_X509V1CertificateSubjectUniqueId;
- certTemp[fieldDex++].FieldValue = *subjectUniqueId;
- }
- if(issuerUniqueId != 0) {
- certTemp[fieldDex].FieldOid = CSSMOID_X509V1CertificateIssuerUniqueId;
- certTemp[fieldDex++].FieldValue = *issuerUniqueId;
- }
-
- for(extNum=0; extNum<numExtensions; extNum++) {
- CSSM_X509_EXTENSION_PTR ext = &extensions[extNum];
- if(ext->format == CSSM_X509_DATAFORMAT_PARSED) {
- certTemp[fieldDex].FieldOid = ext->extnId;
- }
- else {
- certTemp[fieldDex].FieldOid = CSSMOID_X509V3CertificateExtensionCStruct;
- }
- certTemp[fieldDex].FieldValue.Data = (uint8 *)ext;
- certTemp[fieldDex++].FieldValue.Length = sizeof(CSSM_X509_EXTENSION);
- }
- assert(fieldDex == numFields);
-
- /*
- * OK, here we go
- */
- rawCert = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA));
- rawCert->Data = NULL;
- rawCert->Length = 0;
- CSSM_RETURN crtn = CSSM_CL_CertCreateTemplate(clHand,
- fieldDex,
- certTemp,
- rawCert);
- if(crtn) {
- tpCredDebug("CSSM_CL_CertCreateTemplate returned %ld", (long)crtn);
- free(rawCert->Data);
- free(rawCert);
- rawCert = NULL;
- }
-
- /* free the stuff we mallocd to get here */
- free(serialDER.Data);
- free(versionDER.Data);
- free(certTemp);
- if(freeRawKey) {
- tpFreeCssmData(*this, &rawPubKey.KeyData, CSSM_FALSE);
- }
- if(crtn) {
- CssmError::throwMe(crtn);
- }
-}
-
-/* given a cert and a ReferenceIdentifier, fill in ReferenceIdentifier and
- * add it and the cert to tpCredMap. */
-void AppleTPSession::addCertToMap(
- const CSSM_DATA *cert,
- CSSM_DATA_PTR refId)
-{
- StLock<Mutex> _(tpCredMapLock);
-
- TpCredHandle hand = reinterpret_cast<TpCredHandle>(cert);
- intToDER(hand, *refId, *this);
- tpCredMap[hand] = cert;
-}
-
-/* given a ReferenceIdentifier, obtain associated cert and remove from the map */
-CSSM_DATA_PTR AppleTPSession::getCertFromMap(
- const CSSM_DATA *refId)
-{
- StLock<Mutex> _(tpCredMapLock);
- CSSM_DATA_PTR rtn = NULL;
-
- if((refId == NULL) || (refId->Data == NULL)) {
- return NULL;
- }
- TpCredHandle hand = DERToInt(*refId);
- credMap::iterator it = tpCredMap.find(hand);
- if(it == tpCredMap.end()) {
- return NULL;
- }
- rtn = const_cast<CSSM_DATA *>(it->second);
- tpCredMap.erase(hand);
- return rtn;
-}
-
-/*
- * SubmitCredRequest, CSR form.
- */
-void AppleTPSession::SubmitCsrRequest(
- const CSSM_TP_REQUEST_SET &RequestInput,
- const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthContext,
- sint32 &EstimatedTime, // RETURNED
- CssmData &ReferenceIdentifier) // RETURNED
-{
- CSSM_DATA_PTR csrPtr = NULL;
- CSSM_CC_HANDLE sigHand = 0;
- CSSM_APPLE_CL_CSR_REQUEST csrReq;
-
- memset(&csrReq, 0, sizeof(csrReq));
-
- /* for now we're using the same struct for input as the the normal
- * X509 cert request. */
- CSSM_APPLE_TP_CERT_REQUEST *certReq =
- (CSSM_APPLE_TP_CERT_REQUEST *)RequestInput.Requests;
- if((certReq->cspHand == 0) ||
- (certReq->clHand == 0) ||
- (certReq->certPublicKey == NULL) ||
- (certReq->issuerPrivateKey == NULL) ||
- (certReq->signatureOid.Data == NULL)) {
- CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS);
- }
-
- /* convert ref public key to raw per CL requirements */
- const CSSM_KEY *subjectPubKey = certReq->certPublicKey;
- const CSSM_KEY *actPubKey = NULL;
- CSSM_BOOL freeRawKey = CSSM_FALSE;
- CSSM_KEY rawPubKey;
-
- switch(subjectPubKey->KeyHeader.BlobType) {
- case CSSM_KEYBLOB_RAW:
- actPubKey = subjectPubKey;
- break;
- case CSSM_KEYBLOB_REFERENCE:
- refKeyToRaw(certReq->cspHand, subjectPubKey, &rawPubKey);
- actPubKey = &rawPubKey;
- freeRawKey = CSSM_TRUE;
- break;
- default:
- tpCredDebug("SubmitCsrRequest: bad key blob type (%u)",
- (unsigned)subjectPubKey->KeyHeader.BlobType);
- CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS);
- }
-
- /* cook up a CL-passthrough-specific request */
- csrReq.subjectNameX509 = buildX509Name(certReq->subjectNames,
- certReq->numSubjectNames);
- csrReq.signatureAlg = certReq->signatureAlg;
- csrReq.signatureOid = certReq->signatureOid;
- csrReq.cspHand = certReq->cspHand;
- csrReq.subjectPublicKey = actPubKey;
- csrReq.subjectPrivateKey = certReq->issuerPrivateKey;
- csrReq.challengeString = certReq->challengeString;
-
- /* A crypto handle to pass to the CL */
- CSSM_RETURN crtn;
- crtn = CSSM_CSP_CreateSignatureContext(certReq->cspHand,
- certReq->signatureAlg,
- (CallerAuthContext ? CallerAuthContext->CallerCredentials : NULL),
- certReq->issuerPrivateKey,
- &sigHand);
- if(crtn) {
- tpCredDebug("CSSM_CSP_CreateSignatureContext returned %ld", (long)crtn);
- goto abort;
- }
-
- /* down to the CL to do the actual work */
- crtn = CSSM_CL_PassThrough(certReq->clHand,
- sigHand,
- CSSM_APPLEX509CL_OBTAIN_CSR,
- &csrReq,
- (void **)&csrPtr);
- if(crtn) {
- tpCredDebug("CSSM_CL_PassThrough returned %ld", (long)crtn);
- goto abort;
- }
-
- /* save it for retrieval by RetrieveCredResult */
- addCertToMap(csrPtr, &ReferenceIdentifier);
- EstimatedTime = 0;
-
-abort:
- /* free local resources */
- if(csrReq.subjectNameX509) {
- freeX509Name(csrReq.subjectNameX509);
- }
- if(sigHand) {
- CSSM_DeleteContext(sigHand);
- }
- if(freeRawKey) {
- tpFreeCssmData(*this, &rawPubKey.KeyData, CSSM_FALSE);
- }
- if(crtn) {
- CssmError::throwMe(crtn);
- }
-}
-
-/*
- * Submit cred (cert) request. Currently the only form of request we
- * handle is the basis "sign this cert with key right now", with policy OI
- * CSSMOID_APPLE_TP_LOCAL_CERT_GEN.
- */
-void AppleTPSession::SubmitCredRequest(
- const CSSM_TP_AUTHORITY_ID *PreferredAuthority,
- CSSM_TP_AUTHORITY_REQUEST_TYPE RequestType,
- const CSSM_TP_REQUEST_SET &RequestInput,
- const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthContext,
- sint32 &EstimatedTime,
- CssmData &ReferenceIdentifier)
-{
- /* free all of these on return if non-NULL */
- CSSM_DATA_PTR certTemplate = NULL;
- CSSM_X509_TIME_PTR notBeforeX509 = NULL;
- CSSM_X509_TIME_PTR notAfterX509 = NULL;
- CSSM_X509_NAME_PTR subjectX509 = NULL;
- CSSM_X509_NAME_PTR issuerX509 = NULL;
- CSSM_X509_EXTENSION_PTR extens509 = NULL;
- CSSM_CC_HANDLE sigContext = 0;
-
- /* this gets saved on success */
- CSSM_DATA_PTR signedCert = NULL;
-
- /* validate rather limited set of input args */
- if(PreferredAuthority != NULL) {
- CssmError::throwMe(CSSMERR_TP_INVALID_AUTHORITY);
- }
- if(RequestType != CSSM_TP_AUTHORITY_REQUEST_CERTISSUE) {
- CssmError::throwMe(CSSMERR_TP_UNSUPPORTED_SERVICE);
- }
- if(CallerAuthContext == NULL) {
- CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER);
- }
- if((RequestInput.NumberOfRequests != 1) ||
- (RequestInput.Requests == NULL)) {
- CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS);
- }
-
- /* Apple-specific args */
- const CSSM_TP_POLICYINFO *tpPolicy = &CallerAuthContext->Policy;
- if((tpPolicy->NumberOfPolicyIds != 1) ||
- (tpPolicy->PolicyIds == NULL)) {
- CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER);
- }
- if(tpCompareCssmData(&tpPolicy->PolicyIds->FieldOid,
- &CSSMOID_APPLE_TP_CSR_GEN)) {
- /* break out to CSR-specific code */
- SubmitCsrRequest(RequestInput, CallerAuthContext, EstimatedTime, ReferenceIdentifier);
- return;
- }
- else if(!tpCompareCssmData(&tpPolicy->PolicyIds->FieldOid,
- &CSSMOID_APPLE_TP_LOCAL_CERT_GEN)) {
- CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS);
- }
-
- CSSM_APPLE_TP_CERT_REQUEST *certReq =
- (CSSM_APPLE_TP_CERT_REQUEST *)RequestInput.Requests;
- if((certReq->cspHand == 0) ||
- (certReq->clHand == 0) ||
- (certReq->certPublicKey == NULL) ||
- (certReq->issuerPrivateKey == NULL)) {
- CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS);
- }
- if((certReq->numExtensions != 0) & (certReq->extensions == NULL)) {
- CssmError::throwMe(CSSMERR_TP_INVALID_POINTER);
- }
-
- CSSM_RETURN ourRtn = CSSM_OK;
-
- try {
- /* convert caller's friendly names and times to CDSA style */
- subjectX509 = buildX509Name(certReq->subjectNames, certReq->numSubjectNames);
- if(certReq->issuerNames != NULL) {
- issuerX509 = buildX509Name(certReq->issuerNames, certReq->numIssuerNames);
- }
- else if(certReq->issuerNameX509) {
- /* caller obtained this from an existing signer's cert */
- issuerX509 = certReq->issuerNameX509;
- }
- else {
- /* self-signed */
- issuerX509 = subjectX509;
- }
- notBeforeX509 = buildX509Time(certReq->notBefore);
- notAfterX509 = buildX509Time(certReq->notAfter);
-
- if(certReq->numExtensions != 0) {
- /* convert extensions array from CE_DataAndType to CSSM_X509_EXTENSION */
- extens509 = (CSSM_X509_EXTENSION *)malloc(sizeof(CSSM_X509_EXTENSION) *
- certReq->numExtensions);
- memset(extens509, 0, sizeof(CSSM_X509_EXTENSION) *
- certReq->numExtensions);
- for(unsigned dex=0; dex<certReq->numExtensions; dex++) {
- CSSM_X509_EXTENSION *extn = &extens509[dex];
- CE_DataAndType *cdt = &certReq->extensions[dex];
- void *parsedValue;
- CSSM_OID extnId;
-
- switch(cdt->type) {
- case DT_AuthorityKeyID:
- parsedValue = &cdt->extension.authorityKeyID;
- extnId = CSSMOID_AuthorityKeyIdentifier;
- break;
- case DT_SubjectKeyID:
- parsedValue = &cdt->extension.subjectKeyID;
- extnId = CSSMOID_SubjectKeyIdentifier;
- break;
- case DT_KeyUsage:
- parsedValue = &cdt->extension.keyUsage;
- extnId = CSSMOID_KeyUsage;
- break;
- case DT_SubjectAltName:
- parsedValue = &cdt->extension.subjectAltName;
- extnId = CSSMOID_SubjectAltName;
- break;
- case DT_IssuerAltName:
- parsedValue = &cdt->extension.issuerAltName;
- extnId = CSSMOID_IssuerAltName;
- break;
- case DT_ExtendedKeyUsage:
- parsedValue = &cdt->extension.extendedKeyUsage;
- extnId = CSSMOID_ExtendedKeyUsage;
- break;
- case DT_BasicConstraints:
- parsedValue = &cdt->extension.basicConstraints;
- extnId = CSSMOID_BasicConstraints;
- break;
- case DT_CertPolicies:
- parsedValue = &cdt->extension.certPolicies;
- extnId = CSSMOID_CertificatePolicies;
- break;
- case DT_NetscapeCertType:
- parsedValue = &cdt->extension.netscapeCertType;
- extnId = CSSMOID_NetscapeCertType;
- break;
- case DT_CrlDistributionPoints:
- parsedValue = &cdt->extension.crlDistPoints;
- extnId = CSSMOID_CrlDistributionPoints;
- break;
- case DT_AuthorityInfoAccess:
- parsedValue = &cdt->extension.authorityInfoAccess;
- extnId = CSSMOID_AuthorityInfoAccess;
- break;
- case DT_Other:
- default:
- tpCredDebug("SubmitCredRequest: DT_Other not supported");
- CssmError::throwMe(CSSMERR_TP_UNKNOWN_TAG);
- // NOT REACHED
- }
- extn->extnId = extnId;
- extn->critical = cdt->critical;
- extn->format = CSSM_X509_DATAFORMAT_PARSED;
- extn->value.parsedValue = parsedValue;
- extn->BERvalue.Data = NULL;
- extn->BERvalue.Length = 0;
- } /* for each extension */
- } /* converting extensions */
-
- /* cook up the unsigned template */
- makeCertTemplate(certReq->clHand,
- certReq->cspHand,
- certReq->serialNumber,
- issuerX509,
- subjectX509,
- notBeforeX509,
- notAfterX509,
- certReq->certPublicKey,
- certReq->signatureOid,
- NULL, // subjectUniqueID, not used here (yet)
- NULL, // issuerUniqueId
- extens509,
- certReq->numExtensions,
- certTemplate);
-
- /* create signature context */
- ourRtn = CSSM_CSP_CreateSignatureContext(certReq->cspHand,
- certReq->signatureAlg,
- (CallerAuthContext ? CallerAuthContext->CallerCredentials : NULL),
- certReq->issuerPrivateKey,
- &sigContext);
- if(ourRtn) {
- tpCredDebug("CSSM_CSP_CreateSignatureContext returned %ld", (long)ourRtn);
- CssmError::throwMe(ourRtn);
- }
-
- signedCert = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA));
- signedCert->Data = NULL;
- signedCert->Length = 0;
- ourRtn = CSSM_CL_CertSign(certReq->clHand,
- sigContext,
- certTemplate, // CertToBeSigned
- NULL, // SignScope
- 0, // ScopeSize,
- signedCert);
- if(ourRtn) {
- tpCredDebug("CSSM_CL_CertSign returned %ld", (long)ourRtn);
- CssmError::throwMe(ourRtn);
- }
-
- /* save it for retrieval by RetrieveCredResult */
- addCertToMap(signedCert, &ReferenceIdentifier);
- EstimatedTime = 0;
- }
- catch (const CssmError &cerr) {
- tpCredDebug("SubmitCredRequest: CSSM error %ld", (long)cerr.error);
- ourRtn = cerr.error;
- }
- catch(...) {
- tpCredDebug("SubmitCredRequest: unknown exception");
- ourRtn = CSSMERR_TP_INTERNAL_ERROR; // ??
- }
-
- /* free reources */
- tpFreeCssmData(*this, certTemplate, CSSM_TRUE);
- freeX509Name(subjectX509);
- if(certReq->issuerNames) {
- freeX509Name(issuerX509);
- }
- /* else same as subject */
- freeX509Time(notBeforeX509);
- freeX509Time(notAfterX509);
- if(extens509) {
- free(extens509);
- }
- if(sigContext != 0) {
- CSSM_DeleteContext(sigContext);
- }
- if(ourRtn) {
- CssmError::throwMe(ourRtn);
- }
-}
-
-void AppleTPSession::RetrieveCredResult(
- const CssmData &ReferenceIdentifier,
- const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials,
- sint32 &EstimatedTime,
- CSSM_BOOL &ConfirmationRequired,
- CSSM_TP_RESULT_SET_PTR &RetrieveOutput)
-{
- CSSM_DATA *cert = getCertFromMap(&ReferenceIdentifier);
-
- if(cert == NULL) {
- tpCredDebug("RetrieveCredResult: refId not found");
- CssmError::throwMe(CSSMERR_TP_INVALID_IDENTIFIER);
- }
-
- /* CSSM_TP_RESULT_SET.Results points to a CSSM_ENCODED_CERT */
- CSSM_ENCODED_CERT *encCert = (CSSM_ENCODED_CERT *)malloc(sizeof(CSSM_ENCODED_CERT));
- encCert->CertType = CSSM_CERT_X_509v3;
- encCert->CertEncoding = CSSM_CERT_ENCODING_DER;
-
- /*
- * caller must free all three:
- * CSSM_TP_RESULT_SET_PTR RetrieveOutput
- * RetrieveOutput->Results (CSSM_ENCODED_CERT *encCert)
- * encCert->CertBlob.Data (the actual cert)
- * We free:
- * cert -- mallocd in SubmitCredRequest
- */
- encCert->CertBlob = *cert;
- RetrieveOutput = (CSSM_TP_RESULT_SET_PTR)malloc(
- sizeof(CSSM_TP_RESULT_SET));
- RetrieveOutput->Results = encCert;
- RetrieveOutput->NumberOfResults = 1;
- ConfirmationRequired = CSSM_FALSE;
- free(cert);
- EstimatedTime = 0;
-}