+++ /dev/null
-/*
- * CertBuilderApp.cpp - support for constructing certs, CDSA version
- */
-
-#include "clutils.h"
-#include <utilLib/common.h>
-#include "CertBuilderApp.h"
-#include "timeStr.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <Security/oidscert.h>
-#include <Security/oidsalg.h>
-#include <Security/x509defs.h>
-#include <Security/SecAsn1Coder.h>
-/* private header */
-#include <Security/keyTemplates.h>
-
-/*
- * 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 *CB_BuildX509Name(
- const CB_NameOid *nameArray,
- unsigned numNames)
-{
- CSSM_X509_NAME *top = (CSSM_X509_NAME *)appMalloc(sizeof(CSSM_X509_NAME), 0);
- if(top == NULL) {
- return NULL;
- }
- top->numberOfRDNs = numNames;
- top->RelativeDistinguishedName =
- (CSSM_X509_RDN_PTR)appMalloc(sizeof(CSSM_X509_RDN) * numNames, 0);
- if(top->RelativeDistinguishedName == NULL) {
- return NULL;
- }
- CSSM_X509_RDN_PTR rdn;
- const CB_NameOid *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)
- appMalloc(sizeof(CSSM_X509_TYPE_VALUE_PAIR), 0);
- CSSM_X509_TYPE_VALUE_PAIR_PTR atvp = rdn->AttributeTypeAndValue;
- if(atvp == NULL) {
- return NULL;
- }
- appCopyCssmData(nameOid->oid, &atvp->type);
- atvp->valueType = BER_TAG_PRINTABLE_STRING;
- atvp->value.Length = strlen(nameOid->string);
- atvp->value.Data = (uint8 *)CSSM_MALLOC(atvp->value.Length);
- memmove(atvp->value.Data, nameOid->string, atvp->value.Length);
- }
- return top;
-}
-
-/* free the CSSM_X509_NAME obtained from CB_BuildX509Name */
-void CB_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];
- CSSM_FREE(atvp->type.Data);
- CSSM_FREE(atvp->value.Data);
- }
- CSSM_FREE(rdn->AttributeTypeAndValue);
- }
- }
- CSSM_FREE(top->RelativeDistinguishedName);
- CSSM_FREE(top);
-}
-
-/* Obtain a CSSM_X509_TIME representing "now" plus specified seconds, or
- * from a preformatted gen time string */
-CSSM_X509_TIME *CB_BuildX509Time(
- unsigned secondsFromNow, /* ignored if timeStr non-NULL */
- const char *timeStr) /* optional, from genTimeAtNowPlus */
-{
- CSSM_X509_TIME *xtime = (CSSM_X509_TIME *)appMalloc(sizeof(CSSM_X509_TIME), 0);
- if(xtime == NULL) {
- return NULL;
- }
- xtime->timeType = BER_TAG_GENERALIZED_TIME;
- char *ts;
- if(timeStr == NULL) {
- ts = genTimeAtNowPlus(secondsFromNow);
- }
- else {
- ts = (char *)appMalloc(strlen(timeStr) + 1, 0);
- strcpy(ts, timeStr);
- }
- xtime->time.Data = (uint8 *)ts;
- xtime->time.Length = strlen(ts);
- return xtime;
-}
-
-/* Free CSSM_X509_TIME obtained in CB_BuildX509Time */
-void CB_FreeX509Time(
- CSSM_X509_TIME *xtime)
-{
- if(xtime == NULL) {
- return;
- }
- freeTimeString((char *)xtime->time.Data);
- appFree(xtime, 0);
-}
-
-/*
- * Encode an OID as a CSSM_X509_ALGORITHM_IDENTIFIER.
- * Returns nonzero on error.
- * Returned data is appMallocd's caller must appFree.
- */
-int encodeParamOid(
- const CSSM_OID *paramOid,
- CSSM_DATA *params)
-{
- SecAsn1CoderRef coder = NULL;
- if(SecAsn1CoderCreate(&coder)) {
- printf("***Error in SecAsn1CoderCreate()\n");
- return -1;
- }
-
- CSSM_X509_ALGORITHM_IDENTIFIER algParams;
- memset(&algParams, 0, sizeof(algParams));
- algParams.algorithm = *paramOid;
- CSSM_DATA encoded = {0, NULL};
- int ourRtn = 0;
- if(SecAsn1EncodeItem(coder, &algParams, kSecAsn1AlgorithmIDTemplate,
- &encoded)) {
- printf("***Error encoding CSSM_X509_ALGORITHM_IDENTIFIER\n");
- ourRtn = -1;
- goto errOut;
- }
-
- /* That data is in the coder's memory space: copy ou9t to caller */
- if(appCopyCssmData(&encoded, params)) {
- printf("***encodeParamOid malloc failure\n");
- ourRtn = -1;
- }
-errOut:
- SecAsn1CoderRelease(coder);
- return ourRtn;
-}
-
-/*
- * Cook up an unsigned cert.
- * This is just a wrapper for CSSM_CL_CertCreateTemplate().
- */
-
-#define ALWAYS_SET_VERSION 0
-
-CSSM_DATA_PTR CB_MakeCertTemplate(
- /* required */
- CSSM_CL_HANDLE clHand,
- 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_PTR subjectPubKey,
- CSSM_ALGORITHMS sigAlg, // e.g., CSSM_ALGID_SHA1WithRSA
- /* optional */
- const CSSM_DATA *subjectUniqueId,
- const CSSM_DATA *issuerUniqueId,
- CSSM_X509_EXTENSION *extensions,
- unsigned numExtensions)
-{
- CSSM_FIELD *certTemp;
- unsigned fieldDex = 0; // index into certTemp
- CSSM_DATA_PTR serialDER = NULL; // serial number, DER format
- CSSM_DATA_PTR rawCert; // from CSSM_CL_CertCreateTemplate
- unsigned version = 0;
- CSSM_DATA_PTR versionDER = NULL;
- unsigned extNum;
- int setVersion = ALWAYS_SET_VERSION;
- const CSSM_OID *paramOid = NULL;
-
- /* convert uint32-style algorithm to the associated struct */
- CSSM_X509_ALGORITHM_IDENTIFIER algId;
- switch(sigAlg) {
- case CSSM_ALGID_SHA1WithRSA:
- algId.algorithm = CSSMOID_SHA1WithRSA;
- break;
- case CSSM_ALGID_MD5WithRSA:
- algId.algorithm = CSSMOID_MD5WithRSA;
- break;
- case CSSM_ALGID_MD2WithRSA:
- algId.algorithm = CSSMOID_MD2WithRSA;
- break;
- case CSSM_ALGID_FEE_MD5:
- algId.algorithm = CSSMOID_APPLE_FEE_MD5;
- break;
- case CSSM_ALGID_FEE_SHA1:
- algId.algorithm = CSSMOID_APPLE_FEE_SHA1;
- break;
- case CSSM_ALGID_SHA1WithECDSA:
- algId.algorithm = CSSMOID_ECDSA_WithSHA1;
- break;
- case CSSM_ALGID_SHA1WithDSA:
- algId.algorithm = CSSMOID_SHA1WithDSA_CMS;
- break;
- case CSSM_ALGID_SHA224WithRSA:
- algId.algorithm = CSSMOID_SHA224WithRSA;
- break;
- case CSSM_ALGID_SHA256WithRSA:
- algId.algorithm = CSSMOID_SHA256WithRSA;
- break;
- case CSSM_ALGID_SHA384WithRSA:
- algId.algorithm = CSSMOID_SHA384WithRSA;
- break;
- case CSSM_ALGID_SHA512WithRSA:
- algId.algorithm = CSSMOID_SHA512WithRSA;
- break;
- /* These specify the digest algorithm via an additional parameter OID */
- case CSSM_ALGID_SHA224WithECDSA:
- algId.algorithm = CSSMOID_ECDSA_WithSpecified;
- paramOid = &CSSMOID_SHA224;
- break;
- case CSSM_ALGID_SHA256WithECDSA:
- algId.algorithm = CSSMOID_ECDSA_WithSpecified;
- paramOid = &CSSMOID_SHA256;
- break;
- case CSSM_ALGID_SHA384WithECDSA:
- algId.algorithm = CSSMOID_ECDSA_WithSpecified;
- paramOid = &CSSMOID_SHA384;
- break;
- case CSSM_ALGID_SHA512WithECDSA:
- algId.algorithm = CSSMOID_ECDSA_WithSpecified;
- paramOid = &CSSMOID_SHA512;
- break;
- default:
- printf("CB_MakeCertTemplate: unknown sig alg (%u)\n", (unsigned)sigAlg);
- return NULL;
- }
- if(paramOid != NULL) {
- /* not-quite-trivial encoding of digest algorithm */
- if(encodeParamOid(paramOid, &algId.parameters)) {
- return NULL;
- }
- }
- else {
- algId.parameters.Data = NULL;
- algId.parameters.Length = 0;
- }
-
- /*
- * version, we infer
- * serialNumber thru subjectPubKey
- */
- unsigned numFields = 7 + numExtensions;
- if(numExtensions) {
- version = 2;
- }
- if(subjectUniqueId) {
- numFields++;
- if(version == 0) {
- version = 1;
- }
- }
- if(issuerUniqueId) {
- numFields++;
- if(version == 0) {
- version = 1;
- }
- }
- if(version > 0) {
- setVersion = 1;
- }
- if(setVersion) {
- numFields++;
- }
-
- certTemp = (CSSM_FIELD *)CSSM_MALLOC(sizeof(CSSM_FIELD) * numFields);
-
- /* version */
- if(setVersion) {
- versionDER = intToDER(version);
- certTemp[fieldDex].FieldOid = CSSMOID_X509V1Version;
- certTemp[fieldDex++].FieldValue = *versionDER;
- }
-
- /* serial number */
- serialDER = intToDER(serialNumber);
- 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 *)subjectPubKey;
- 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);
- }
- if(fieldDex != numFields) {
- printf("CB_MakeCertTemplate numFields screwup\n");
- return NULL;
- }
-
- /*
- * OK, here we go
- */
- rawCert = (CSSM_DATA_PTR)CSSM_MALLOC(sizeof(CSSM_DATA));
- rawCert->Data = NULL;
- rawCert->Length = 0;
- CSSM_RETURN crtn = CSSM_CL_CertCreateTemplate(clHand,
- fieldDex,
- certTemp,
- rawCert);
- if(crtn) {
- printError("CSSM_CL_CertCreateTemplate", crtn);
- appFreeCssmData(rawCert, CSSM_TRUE);
- rawCert = NULL;
- }
-
- /* free the stuff we mallocd to get here */
- appFreeCssmData(serialDER, CSSM_TRUE);
- appFreeCssmData(versionDER, CSSM_TRUE);
- CSSM_FREE(certTemp);
- if((paramOid != NULL) && (algId.parameters.Data != NULL)) {
- CSSM_FREE(algId.parameters.Data);
- }
- return rawCert;
-}