signerAndSubjSsl.cpp [plain text]
#include <utilLib/common.h>
#include <utilLib/cspwrap.h>
#include <security_cdsa_utils/cuFileIo.h>
#include <clAppUtils/clutils.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <Security/cssm.h>
#include <Security/x509defs.h>
#include <Security/oidsattr.h>
#include <Security/oidscert.h>
#include <Security/oidsalg.h>
#include <Security/certextensions.h>
#include <Security/cssmapple.h>
#include <string.h>
#define SUBJ_KEY_LABEL "subjectKey"
#define ROOT_KEY_LABEL "rootKey"
#define SIG_ALG_DEFAULT CSSM_ALGID_SHA1WithRSA
#define SIG_OID_DEFAULT CSSMOID_SHA1WithRSA
#define KEY_ALG_DEFAULT CSSM_ALGID_RSA
#define ROOT_CERT_FILE_NAME "ssRootCert.der"
#define SUBJ_CERT_FILE_NAME "ssSubjCert.der"
#define PUB_KEY_IS_REF CSSM_TRUE
static void usage(char **argv)
{
printf("Usage: %s [options]\n", argv[0]);
printf("Options:\n");
printf(" i=IP_Address for subjectAltName\n");
printf(" d=dnsName for subjectAltName\n");
printf(" k=keySizeInBits\n");
printf(" q(uiet)\n");
exit(1);
}
CSSM_APPLE_TP_NAME_OID rootRdn[] =
{
{ "Apple Computer", &CSSMOID_OrganizationName },
{ "The Big Cheese", &CSSMOID_Title }
};
#define NUM_ROOT_NAMES (sizeof(rootRdn) / sizeof(CSSM_APPLE_TP_NAME_OID))
CSSM_APPLE_TP_NAME_OID subjRdn[] =
{
{ "Apple Computer", &CSSMOID_OrganizationName },
{ "something.org", &CSSMOID_CommonName }
};
#define NUM_SUBJ_NAMES (sizeof(subjRdn) / sizeof(CSSM_APPLE_TP_NAME_OID))
static int convertIp(
const char *str,
uint8 *buf)
{
char cbuf[4];
for(unsigned dex=0; dex<3; dex++) {
char *nextDot = strchr(str, '.');
if(nextDot == NULL) {
return 1;
}
memmove(cbuf, str, nextDot - str);
*buf = atoi(cbuf);
buf++; str = nextDot + 1;
}
if(str == NULL) {
return 1;
}
*buf = atoi(str);
return 0;
}
int main(int argc, char **argv)
{
CSSM_CL_HANDLE clHand; CSSM_CSP_HANDLE cspHand; CSSM_TP_HANDLE tpHand; CSSM_DATA signedRootCert; CSSM_DATA signedSubjCert; CSSM_KEY subjPubKey; CSSM_KEY subjPrivKey; CSSM_KEY rootPubKey; CSSM_KEY rootPrivKey; CSSM_RETURN crtn;
int arg;
unsigned errorCount = 0;
CSSM_DATA refId; CSSM_APPLE_TP_CERT_REQUEST certReq;
CSSM_TP_REQUEST_SET reqSet;
sint32 estTime;
CSSM_BOOL confirmRequired;
CSSM_TP_RESULT_SET_PTR resultSet;
CSSM_ENCODED_CERT *encCert;
CSSM_TP_CALLERAUTH_CONTEXT CallerAuthContext;
CSSM_FIELD policyId;
CE_GeneralNames genNames;
CE_GeneralName genName;
uint8 ipNameBuf[4];
CSSM_ALGORITHMS keyAlg = KEY_ALG_DEFAULT;
CSSM_ALGORITHMS sigAlg = SIG_ALG_DEFAULT;
CSSM_OID sigOid = SIG_OID_DEFAULT;
uint32 keySizeInBits = CSP_KEY_SIZE_DEFAULT;
char *ipAddrs = NULL;
char *dnsName = NULL;
CSSM_BOOL quiet = CSSM_FALSE;
CE_DataAndType rootExts[2];
CE_DataAndType leafExts[2];
unsigned numLeafExts;
for(arg=1; arg<argc; arg++) {
char *argp = argv[arg];
switch(argp[0]) {
case 'k':
keySizeInBits = atoi(&argp[2]);
break;
case 'i':
ipAddrs = &argp[2];
break;
case 'd':
dnsName = &argp[2];
break;
case 'q':
quiet = CSSM_TRUE;
break;
default:
usage(argv);
}
}
if(ipAddrs && dnsName) {
printf("Max of one of {ipAddrs, dnsName} at a time, please.\n");
usage(argv);
}
if(ipAddrs) {
if(convertIp(ipAddrs, ipNameBuf)) {
printf("**Malformed IP address. Aborting.\n");
exit(1);
}
}
clHand = clStartup();
if(clHand == 0) {
return 0;
}
tpHand = tpStartup();
if(tpHand == 0) {
return 0;
}
cspHand = cspStartup();
if(cspHand == 0) {
return 0;
}
crtn = cspGenKeyPair(cspHand,
keyAlg,
SUBJ_KEY_LABEL,
strlen(SUBJ_KEY_LABEL),
keySizeInBits,
&subjPubKey,
#if PUB_KEY_IS_REF
CSSM_TRUE,
#else
CSSM_FALSE, #endif
CSSM_KEYUSE_VERIFY,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
&subjPrivKey,
CSSM_TRUE, CSSM_KEYUSE_SIGN,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
CSSM_FALSE);
if(crtn) {
errorCount++;
goto abort;
}
crtn = cspGenKeyPair(cspHand,
keyAlg,
ROOT_KEY_LABEL,
strlen(ROOT_KEY_LABEL),
keySizeInBits,
&rootPubKey,
CSSM_FALSE, CSSM_KEYUSE_VERIFY,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
&rootPrivKey,
CSSM_TRUE, CSSM_KEYUSE_SIGN,
CSSM_KEYBLOB_RAW_FORMAT_NONE,
CSSM_FALSE);
if(crtn) {
errorCount++;
goto abort;
}
rootExts[0].type = DT_KeyUsage;
rootExts[0].critical = CSSM_FALSE;
rootExts[0].extension.keyUsage =
CE_KU_DigitalSignature | CE_KU_KeyCertSign;
leafExts[0].type = DT_KeyUsage;
leafExts[0].critical = CSSM_FALSE;
leafExts[0].extension.keyUsage = CE_KU_DigitalSignature;
rootExts[1].type = DT_BasicConstraints;
rootExts[1].critical = CSSM_TRUE;
rootExts[1].extension.basicConstraints.cA = CSSM_TRUE;
rootExts[1].extension.basicConstraints.pathLenConstraintPresent =
CSSM_TRUE;
rootExts[1].extension.basicConstraints.pathLenConstraint = 2;
numLeafExts = 1;
if(ipAddrs || dnsName) {
numLeafExts++;
leafExts[1].type = DT_SubjectAltName;
leafExts[1].critical = CSSM_TRUE;
genName.berEncoded = CSSM_FALSE;
if(ipAddrs) {
genName.name.Data = (uint8 *)ipNameBuf;
genName.name.Length = 4;
genName.nameType = GNT_IPAddress;
}
else {
genName.name.Data = (uint8 *)dnsName;
genName.nameType = GNT_DNSName;
genName.name.Length = strlen(dnsName);
}
genNames.numNames = 1;
genNames.generalName = &genName;
leafExts[1].extension.subjectAltName = genNames;
}
memset(&certReq, 0, sizeof(CSSM_APPLE_TP_CERT_REQUEST));
certReq.cspHand = cspHand;
certReq.clHand = clHand;
certReq.serialNumber = 0x12345678;
certReq.numSubjectNames = NUM_ROOT_NAMES;
certReq.subjectNames = rootRdn;
certReq.numIssuerNames = 0;
certReq.issuerNames = NULL;
certReq.certPublicKey = &rootPubKey;
certReq.issuerPrivateKey = &rootPrivKey;
certReq.signatureAlg = sigAlg;
certReq.signatureOid = sigOid;
certReq.notBefore = 0; certReq.notAfter = 10000; certReq.numExtensions = 2;
certReq.extensions = rootExts;
reqSet.NumberOfRequests = 1;
reqSet.Requests = &certReq;
memset(&CallerAuthContext, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT));
memset(&policyId, 0, sizeof(CSSM_FIELD));
policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN;
CallerAuthContext.Policy.NumberOfPolicyIds = 1;
CallerAuthContext.Policy.PolicyIds = &policyId;
crtn = CSSM_TP_SubmitCredRequest(tpHand,
NULL, CSSM_TP_AUTHORITY_REQUEST_CERTISSUE,
&reqSet,
&CallerAuthContext,
&estTime,
&refId);
if(crtn) {
printError("CSSM_TP_SubmitCredRequest", crtn);
errorCount++;
goto abort;
}
crtn = CSSM_TP_RetrieveCredResult(tpHand,
&refId,
NULL, &estTime,
&confirmRequired,
&resultSet);
if(crtn) {
printError("CSSM_TP_RetrieveCredResult", crtn);
errorCount++;
goto abort;
}
if(resultSet == NULL) {
printf("***CSSM_TP_RetrieveCredResult returned NULL result set.\n");
errorCount++;
goto abort;
}
encCert = (CSSM_ENCODED_CERT *)resultSet->Results;
signedRootCert = encCert->CertBlob;
writeFile(ROOT_CERT_FILE_NAME, signedRootCert.Data,
signedRootCert.Length);
if(!quiet) {
printf("...wrote %lu bytes to %s\n", signedRootCert.Length,
ROOT_CERT_FILE_NAME);
}
certReq.serialNumber = 0x8765;
certReq.numSubjectNames = NUM_SUBJ_NAMES;
certReq.subjectNames = subjRdn;
certReq.numIssuerNames = NUM_ROOT_NAMES;
certReq.issuerNames = rootRdn;
certReq.certPublicKey = &subjPubKey;
certReq.issuerPrivateKey = &rootPrivKey;
certReq.numExtensions = numLeafExts;
certReq.extensions = leafExts;
crtn = CSSM_TP_SubmitCredRequest(tpHand,
NULL, CSSM_TP_AUTHORITY_REQUEST_CERTISSUE,
&reqSet,
&CallerAuthContext,
&estTime,
&refId);
if(crtn) {
printError("CSSM_TP_SubmitCredRequest (2)", crtn);
errorCount++;
goto abort;
}
crtn = CSSM_TP_RetrieveCredResult(tpHand,
&refId,
NULL, &estTime,
&confirmRequired,
&resultSet); if(crtn) {
printError("CSSM_TP_RetrieveCredResult (2)", crtn);
errorCount++;
goto abort;
}
if(resultSet == NULL) {
printf("***CSSM_TP_RetrieveCredResult (2) returned NULL result set.\n");
errorCount++;
goto abort;
}
encCert = (CSSM_ENCODED_CERT *)resultSet->Results;
signedSubjCert = encCert->CertBlob;
writeFile(SUBJ_CERT_FILE_NAME, signedSubjCert.Data,
signedSubjCert.Length);
if(!quiet) {
printf("...wrote %lu bytes to %s\n", signedSubjCert.Length,
SUBJ_CERT_FILE_NAME);
}
appFreeCssmData(&signedSubjCert, CSSM_FALSE);
appFreeCssmData(&signedRootCert, CSSM_FALSE);
cspFreeKey(cspHand, &rootPubKey);
cspFreeKey(cspHand, &subjPubKey);
abort:
if(cspHand != 0) {
CSSM_ModuleDetach(cspHand);
}
if(clHand != 0) {
CSSM_ModuleDetach(clHand);
}
if(tpHand != 0) {
CSSM_ModuleDetach(tpHand);
}
return 0;
}