/* * Sign/verify wrappers. */ static CSSM_RETURN sigSign(CSSM_CSP_HANDLE cspHandle, uint32 algorithm, // CSSM_ALGID_SHA1WithRSA, etc. CSSM_KEY_PTR key, // private key const CSSM_DATA *text, CSSM_DATA_PTR sig) { CSSM_CC_HANDLE sigHand; CSSM_RETURN crtn; crtn = CSSM_CSP_CreateSignatureContext(cspHandle, algorithm, NULL, // passPhrase key, &sigHand); if(crtn) { return crtn; } crtn = CSSM_SignData(sigHand, text, 1, CSSM_ALGID_NONE, sig); CSSM_DeleteContext(sigHand); return crtn; }
/* verify a cert using specified key and/or signerCert */ static CSSM_RETURN verifyCert(CSSM_CL_HANDLE clHand, CSSM_CSP_HANDLE cspHand, CSSM_DATA_PTR cert, CSSM_DATA_PTR signerCert, // optional CSSM_KEY_PTR key, // ditto, to work spec one, other, or both CSSM_ALGORITHMS sigAlg, // CSSM_ALGID_SHA1WithRSA, etc. CSSM_RETURN expectResult, const char *opString) { CSSM_RETURN crtn; CSSM_CC_HANDLE signContext = CSSM_INVALID_HANDLE; if(key) { crtn = CSSM_CSP_CreateSignatureContext(cspHand, sigAlg, NULL, // AccessCred key, &signContext); if(crtn) { printf("Failure during %s\n", opString); printError("CSSM_CSP_CreateSignatureContext", crtn); return crtn; } } crtn = CSSM_CL_CertVerify(clHand, signContext, cert, // CertToBeVerified signerCert, // SignerCert NULL, // VerifyScope 0); // ScopeSize if(crtn != expectResult) { printf("Failure during %s\n", opString); if(crtn == CSSM_OK) { printf("Unexpected CSSM_CL_CertVerify success\n"); } else if(expectResult == CSSM_OK) { printError("CSSM_CL_CertVerify", crtn); } else { printError("CSSM_CL_CertVerify: expected", expectResult); printError("CSSM_CL_CertVerify: got ", crtn); } return CSSMERR_CL_VERIFICATION_FAILURE; } if(signContext != CSSM_INVALID_HANDLE) { crtn = CSSM_DeleteContext(signContext); if(crtn) { printf("Failure during %s\n", opString); printError("CSSM_DeleteContext", crtn); return crtn; } } return CSSM_OK; }
static int kc_rsa_private_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { struct kc_rsa *kc = RSA_get_app_data(rsa); CSSM_RETURN cret; OSStatus ret; const CSSM_ACCESS_CREDENTIALS *creds; SecKeyRef privKeyRef = (SecKeyRef)kc->item; CSSM_CSP_HANDLE cspHandle; const CSSM_KEY *cssmKey; CSSM_CC_HANDLE sigHandle = 0; CSSM_DATA sig, in; int fret = 0; if (padding != RSA_PKCS1_PADDING) return -1; cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey); if(cret) abort(); cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle); if(cret) abort(); ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &creds); if(ret) abort(); ret = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA, creds, cssmKey, &sigHandle); if(ret) abort(); in.Data = (uint8 *)from; in.Length = flen; sig.Data = (uint8 *)to; sig.Length = kc->keysize; cret = CSSM_SignData(sigHandle, &in, 1, CSSM_ALGID_NONE, &sig); if(cret) { /* cssmErrorString(cret); */ fret = -1; } else fret = sig.Length; if(sigHandle) CSSM_DeleteContext(sigHandle); return fret; }
static int doVerify( CSSM_CSP_HANDLE cspHand, const char *algStr, CSSM_KEY_PTR key, // private CSSM_ALGORITHMS sigAlg, CSSM_RETURN expRtn, // expected result CSSM_BOOL quiet) { uint8 ptextData[PTEXT_SIZE]; CSSM_DATA ptext = {PTEXT_SIZE, ptextData}; uint8 sigData[PTEXT_SIZE]; CSSM_DATA sig = {PTEXT_SIZE, sigData}; simpleGenData(&ptext, PTEXT_SIZE, PTEXT_SIZE); memset(sigData, 0, PTEXT_SIZE); CSSM_CC_HANDLE cryptHand = 0; CSSM_RETURN crtn; crtn = CSSM_CSP_CreateSignatureContext(cspHand, sigAlg, NULL, // passPhrase key, &cryptHand); if(crtn) { printError("CSSM_CSP_CreateSignatureContext (2)", crtn); return testError(quiet); } int irtn = 0; crtn = CSSM_VerifyData(cryptHand, &ptext, 1, CSSM_ALGID_NONE, &sig); if(crtn != expRtn) { if(expRtn == CSSM_OK) { printError("CSSM_VerifyData", crtn); printf("Unexpected error verifying with %s\n", algStr); } else { printf("***Verify with %s: expected %s, got %s.\n", algStr, cssmErrToStr(expRtn), cssmErrToStr(crtn)); } irtn = testError(quiet); } CSSM_DeleteContext(cryptHand); return irtn; }
static CSSM_RETURN sigVerify(CSSM_CSP_HANDLE cspHand, uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. CSSM_KEY_PTR key, // public key const CSSM_DATA *text, const CSSM_DATA *sig, uint32 digestAlg, // optional for raw signing CSSM_BOOL noPad) // true --> add PADDING_NONE to context { CSSM_CC_HANDLE sigHand; CSSM_RETURN crtn; crtn = CSSM_CSP_CreateSignatureContext(cspHand, algorithm, NULL, // passPhrase key, &sigHand); if(crtn) { printError("CSSM_CSP_CreateSignatureContext", crtn); return crtn; } if(noPad) { crtn = AddContextAttribute(sigHand, CSSM_ATTRIBUTE_PADDING, sizeof(uint32), CAT_Uint32, NULL, CSSM_PADDING_NONE); if(crtn) { return crtn; } } crtn = CSSM_VerifyData(sigHand, text, 1, digestAlg, sig); if(crtn) { printError("CSSM_VerifyData", crtn); } CSSM_DeleteContext(sigHand); return crtn; }
int main(int argc, char **argv) { CSSM_CL_HANDLE clHand; // CL handle CSSM_X509_NAME *subjName; CSSM_X509_NAME *rootName; CSSM_X509_TIME *notBefore; // UTC-style "not before" time CSSM_X509_TIME *notAfter; // UTC-style "not after" time CSSM_DATA_PTR rawCert; // from CSSM_CL_CertCreateTemplate CSSM_DATA signedRootCert; // from CSSM_CL_CertSign CSSM_DATA signedSubjCert; // from CSSM_CL_CertSign CSSM_CSP_HANDLE cspHand; // CSP handle CSSM_KEY subjPubKey; // subject's RSA public key blob CSSM_KEY subjPrivKey; // subject's RSA private key - ref format CSSM_KEY rootPubKey; // root's RSA public key blob CSSM_KEY rootPrivKey; // root's RSA private key - ref format CSSM_RETURN crtn; CSSM_KEY_PTR extractRootKey; // from CSSM_CL_CertGetKeyInfo() CSSM_KEY_PTR extractSubjKey; // ditto CSSM_CC_HANDLE signContext; // for signing/verifying the cert unsigned badByte; int arg; unsigned errorCount = 0; /* user-spec'd variables */ CSSM_BOOL writeBlobs = CSSM_FALSE; CSSM_ALGORITHMS keyAlg = KEY_ALG_DEFAULT; CSSM_ALGORITHMS sigAlg = SIG_ALG_DEFAULT; uint32 keySizeInBits = CSP_KEY_SIZE_DEFAULT; /* * Two extensions. Subject has one (KeyUsage); root has KeyUsage and * BasicConstraints. */ CSSM_X509_EXTENSION exts[2]; CE_KeyUsage keyUsage; CE_BasicConstraints bc; for(arg=1; arg<argc; arg++) { switch(argv[arg][0]) { case 'w': writeBlobs = CSSM_TRUE; break; case 'a': if((argv[arg][1] == '\0') || (argv[arg][2] == '\0')) { usage(argv); } switch(argv[arg][2]) { case 's': keyAlg = CSSM_ALGID_RSA; sigAlg = CSSM_ALGID_SHA1WithRSA; break; case 'm': keyAlg = CSSM_ALGID_RSA; sigAlg = CSSM_ALGID_MD5WithRSA; break; case 'f': keyAlg = CSSM_ALGID_FEE; sigAlg = CSSM_ALGID_FEE_MD5; break; case 'F': keyAlg = CSSM_ALGID_FEE; sigAlg = CSSM_ALGID_FEE_SHA1; break; case 'e': keyAlg = CSSM_ALGID_FEE; sigAlg = CSSM_ALGID_SHA1WithECDSA; break; case 'E': keyAlg = CSSM_ALGID_ECDSA; sigAlg = CSSM_ALGID_SHA1WithECDSA; break; case '7': keyAlg = CSSM_ALGID_ECDSA; sigAlg = CSSM_ALGID_SHA256WithECDSA; break; case '8': keyAlg = CSSM_ALGID_ECDSA; sigAlg = CSSM_ALGID_SHA384WithECDSA; break; case '9': keyAlg = CSSM_ALGID_ECDSA; sigAlg = CSSM_ALGID_SHA512WithECDSA; break; case '2': keyAlg = CSSM_ALGID_RSA; sigAlg = CSSM_ALGID_SHA224WithRSA; break; case '6': keyAlg = CSSM_ALGID_RSA; sigAlg = CSSM_ALGID_SHA256WithRSA; break; case '3': keyAlg = CSSM_ALGID_RSA; sigAlg = CSSM_ALGID_SHA384WithRSA; break; case '5': keyAlg = CSSM_ALGID_RSA; sigAlg = CSSM_ALGID_SHA512WithRSA; break; default: usage(argv); } break; case 'k': keySizeInBits = atoi(&argv[arg][2]); break; default: usage(argv); } } /* connect to CL and CSP */ clHand = clStartup(); if(clHand == 0) { return 0; } cspHand = cspStartup(); if(cspHand == 0) { return 0; } /* subsequent errors to abort: to detach */ /* cook up an RSA key pair for the subject */ crtn = cspGenKeyPair(cspHand, keyAlg, SUBJ_KEY_LABEL, strlen(SUBJ_KEY_LABEL), keySizeInBits, &subjPubKey, CSSM_FALSE, // pubIsRef - should work both ways, but not yet CSSM_KEYUSE_VERIFY, CSSM_KEYBLOB_RAW_FORMAT_NONE, &subjPrivKey, CSSM_FALSE, // privIsRef CSSM_KEYUSE_SIGN, CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_FALSE); if(crtn) { errorCount++; goto abort; } if(writeBlobs) { writeFile(SUBJ_PRIV_KEY_FILE, subjPrivKey.KeyData.Data, subjPrivKey.KeyData.Length); printf("...wrote %lu bytes to %s\n", subjPrivKey.KeyData.Length, SUBJ_PRIV_KEY_FILE); } /* and the root */ crtn = cspGenKeyPair(cspHand, keyAlg, ROOT_KEY_LABEL, strlen(ROOT_KEY_LABEL), keySizeInBits, &rootPubKey, CSSM_FALSE, // pubIsRef - should work both ways, but not yet CSSM_KEYUSE_VERIFY, CSSM_KEYBLOB_RAW_FORMAT_NONE, &rootPrivKey, CSSM_FALSE, // privIsRef CSSM_KEYUSE_SIGN, CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_FALSE); if(crtn) { errorCount++; goto abort; } if(writeBlobs) { writeFile(ROOT_PRIV_KEY_FILE, rootPrivKey.KeyData.Data, rootPrivKey.KeyData.Length); printf("...wrote %lu bytes to %s\n", rootPrivKey.KeyData.Length, ROOT_PRIV_KEY_FILE); } if(compareKeyData(&rootPubKey, &subjPubKey)) { printf("**WARNING: Identical root and subj keys!\n"); } /* * Cook up various cert fields. * First, the RDNs for subject and issuer. */ rootName = CB_BuildX509Name(rootRdn, NUM_ROOT_NAMES); subjName = CB_BuildX509Name(subjRdn, NUM_SUBJ_NAMES); if((rootName == NULL) || (subjName == NULL)) { printf("CB_BuildX509Name failure"); errorCount++; goto abort; } /* not before/after in generalized time format */ notBefore = CB_BuildX509Time(0); notAfter = CB_BuildX509Time(10000); /* A KeyUsage extension for both certs */ exts[0].extnId = CSSMOID_KeyUsage; exts[0].critical = CSSM_FALSE; exts[0].format = CSSM_X509_DATAFORMAT_PARSED; keyUsage = CE_KU_DigitalSignature | CE_KU_KeyCertSign | CE_KU_KeyEncipherment | CE_KU_DataEncipherment; exts[0].value.parsedValue = &keyUsage; exts[0].BERvalue.Data = NULL; exts[0].BERvalue.Length = 0; /* BasicConstraints for root only */ exts[1].extnId = CSSMOID_BasicConstraints; exts[1].critical = CSSM_TRUE; exts[1].format = CSSM_X509_DATAFORMAT_PARSED; bc.cA = CSSM_TRUE; bc.pathLenConstraintPresent = CSSM_TRUE; bc.pathLenConstraint = 2; exts[1].value.parsedValue = &bc; exts[1].BERvalue.Data = NULL; exts[1].BERvalue.Length = 0; /* cook up root cert */ printf("Creating root cert...\n"); rawCert = CB_MakeCertTemplate(clHand, 0x12345678, // serial number rootName, rootName, notBefore, notAfter, &rootPubKey, sigAlg, NULL, // subjUniqueId NULL, // issuerUniqueId exts, // extensions 2); // numExtensions if(rawCert == NULL) { errorCount++; goto abort; } if(writeBlobs) { writeFile(ROOT_TBS_FILE_NAME, rawCert->Data, rawCert->Length); printf("...wrote %lu bytes to %s\n", rawCert->Length, ROOT_TBS_FILE_NAME); } /* Self-sign; this is a root cert */ crtn = CSSM_CSP_CreateSignatureContext(cspHand, sigAlg, NULL, // AccessCred &rootPrivKey, &signContext); if(crtn) { printError("CSSM_CSP_CreateSignatureContext", crtn); errorCount++; goto abort; } signedRootCert.Data = NULL; signedRootCert.Length = 0; crtn = CSSM_CL_CertSign(clHand, signContext, rawCert, // CertToBeSigned NULL, // SignScope 0, // ScopeSize, &signedRootCert); if(crtn) { printError("CSSM_CL_CertSign", crtn); errorCount++; goto abort; } crtn = CSSM_DeleteContext(signContext); if(crtn) { printError("CSSM_DeleteContext", crtn); errorCount++; goto abort; } appFreeCssmData(rawCert, CSSM_TRUE); if(writeBlobs) { writeFile(ROOT_CERT_FILE_NAME, signedRootCert.Data, signedRootCert.Length); printf("...wrote %lu bytes to %s\n", signedRootCert.Length, ROOT_CERT_FILE_NAME); } /* now a subject cert signed by the root cert */ printf("Creating subject cert...\n"); rawCert = CB_MakeCertTemplate(clHand, 0x8765, // serial number rootName, subjName, notBefore, notAfter, &subjPubKey, sigAlg, NULL, // subjUniqueId NULL, // issuerUniqueId exts, // extensions 1); // numExtensions if(rawCert == NULL) { errorCount++; goto abort; } if(writeBlobs) { writeFile(SUBJ_TBS_FILE_NAME, rawCert->Data, rawCert->Length); printf("...wrote %lu bytes to %s\n", rawCert->Length, SUBJ_TBS_FILE_NAME); } /* sign by root */ crtn = CSSM_CSP_CreateSignatureContext(cspHand, sigAlg, NULL, // AccessCred &rootPrivKey, &signContext); if(crtn) { printError("CSSM_CSP_CreateSignatureContext", crtn); errorCount++; goto abort; } signedSubjCert.Data = NULL; signedSubjCert.Length = 0; crtn = CSSM_CL_CertSign(clHand, signContext, rawCert, // CertToBeSigned NULL, // SignScope 0, // ScopeSize, &signedSubjCert); if(crtn) { printError("CSSM_CL_CertSign", crtn); errorCount++; goto abort; } crtn = CSSM_DeleteContext(signContext); if(crtn) { printError("CSSM_DeleteContext", crtn); errorCount++; goto abort; } appFreeCssmData(rawCert, CSSM_TRUE); if(writeBlobs) { writeFile(SUBJ_CERT_FILE_NAME, signedSubjCert.Data, signedSubjCert.Length); printf("...wrote %lu bytes to %s\n", signedSubjCert.Length, SUBJ_CERT_FILE_NAME); } /* Free the stuff we allocd to get here */ CB_FreeX509Name(rootName); CB_FreeX509Name(subjName); CB_FreeX509Time(notBefore); CB_FreeX509Time(notAfter); /* * Extract public keys from the two certs, verify. */ crtn = CSSM_CL_CertGetKeyInfo(clHand, &signedSubjCert, &extractSubjKey); if(crtn) { printError("CSSM_CL_CertGetKeyInfo", crtn); } else { /* compare key data - header is different. * Known header differences: * -- CspID - CSSM_CL_CertGetKeyInfo returns a key with NULL for * this field * -- Format. rootPubKey : 6 (CSSM_KEYBLOB_RAW_FORMAT_BSAFE) * extractRootKey : 1 (CSSM_KEYBLOB_RAW_FORMAT_PKCS1) * -- KeyAttr. rootPubKey : 0x20 (CSSM_KEYATTR_EXTRACTABLE) * extractRootKey : 0x0 */ if(!compareKeyData(extractSubjKey, &subjPubKey)) { printf("***CSSM_CL_CertGetKeyInfo(signedSubjCert) returned bad key data\n"); } if(extractSubjKey->KeyHeader.LogicalKeySizeInBits != subjPubKey.KeyHeader.LogicalKeySizeInBits) { printf("***EffectiveKeySizeInBits mismatch: extract %u subj %u\n", (unsigned)extractSubjKey->KeyHeader.LogicalKeySizeInBits, (unsigned)subjPubKey.KeyHeader.LogicalKeySizeInBits); } } crtn = CSSM_CL_CertGetKeyInfo(clHand, &signedRootCert, &extractRootKey); if(crtn) { printError("CSSM_CL_CertGetKeyInfo", crtn); } else { if(!compareKeyData(extractRootKey, &rootPubKey)) { printf("***CSSM_CL_CertGetKeyInfo(signedRootCert) returned bad key data\n"); } } /* * Verify: */ printf("Verifying certificates...\n"); /* * Verify root cert by root pub key, should succeed. */ if(verifyCert(clHand, cspHand, &signedRootCert, NULL, &rootPubKey, sigAlg, CSSM_OK, "Verify(root by root key)")) { errorCount++; /* continue */ } /* * Verify root cert by root cert, should succeed. */ if(verifyCert(clHand, cspHand, &signedRootCert, &signedRootCert, NULL, CSSM_ALGID_NONE, // sigAlg not used here CSSM_OK, "Verify(root by root cert)")) { errorCount++; /* continue */ } /* * Verify subject cert by root pub key, should succeed. */ if(verifyCert(clHand, cspHand, &signedSubjCert, NULL, &rootPubKey, sigAlg, CSSM_OK, "Verify(subj by root key)")) { errorCount++; /* continue */ } /* * Verify subject cert by root cert, should succeed. */ if(verifyCert(clHand, cspHand, &signedSubjCert, &signedRootCert, NULL, CSSM_ALGID_NONE, // sigAlg not used here CSSM_OK, "Verify(subj by root cert)")) { errorCount++; /* continue */ } /* * Verify subject cert by root cert AND key, should succeed. */ if(verifyCert(clHand, cspHand, &signedSubjCert, &signedRootCert, &rootPubKey, sigAlg, CSSM_OK, "Verify(subj by root cert and key)")) { errorCount++; /* continue */ } /* * Verify subject cert by extracted root pub key, should succeed. */ if(verifyCert(clHand, cspHand, &signedSubjCert, NULL, extractRootKey, sigAlg, CSSM_OK, "Verify(subj by extracted root key)")) { errorCount++; /* continue */ } /* * Verify subject cert by subject pub key, should fail. */ if(verifyCert(clHand, cspHand, &signedSubjCert, NULL, &subjPubKey, sigAlg, CSSMERR_CL_VERIFICATION_FAILURE, "Verify(subj by subj key)")) { errorCount++; /* continue */ } /* * Verify subject cert by subject cert, should fail. */ if(verifyCert(clHand, cspHand, &signedSubjCert, &signedSubjCert, NULL, CSSM_ALGID_NONE, // sigAlg not used here CSSMERR_CL_VERIFICATION_FAILURE, "Verify(subj by subj cert)")) { errorCount++; /* continue */ } /* * Verify erroneous subject cert by root pub key, should fail. */ badByte = genRand(1, signedSubjCert.Length - 1); signedSubjCert.Data[badByte] ^= 0x55; if(verifyCert(clHand, cspHand, &signedSubjCert, NULL, &rootPubKey, sigAlg, CSSMERR_CL_VERIFICATION_FAILURE, "Verify(bad subj by root key)")) { errorCount++; /* continue */ } /* free/delete certs and keys */ appFreeCssmData(&signedSubjCert, CSSM_FALSE); appFreeCssmData(&signedRootCert, CSSM_FALSE); cspFreeKey(cspHand, &rootPubKey); cspFreeKey(cspHand, &subjPubKey); /* These don't work because CSSM_CL_CertGetKeyInfo() gives keys with * a bogus GUID. This may be a problem with the Apple CSP... * cspFreeKey(cspHand, extractRootKey); cspFreeKey(cspHand, extractSubjKey); * * do it this way instead...*/ CSSM_FREE(extractRootKey->KeyData.Data); CSSM_FREE(extractSubjKey->KeyData.Data); /* need to do this regardless...*/ CSSM_FREE(extractRootKey); CSSM_FREE(extractSubjKey); abort: if(cspHand != 0) { CSSM_ModuleDetach(cspHand); } if(errorCount) { printf("Signer/Subject test failed with %d errors\n", errorCount); } else { printf("Signer/Subject test succeeded\n"); } return 0; }
SECStatus ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, PRBool isTLS, KeyType keyType) { SECStatus rv = SECFailure; PRBool doDerEncode = PR_FALSE; unsigned int signatureLen; OSStatus status = noErr; CSSM_CSP_HANDLE cspHandle = 0; const CSSM_KEY *cssmKey = NULL; CSSM_ALGORITHMS sigAlg; CSSM_ALGORITHMS digestAlg; const CSSM_ACCESS_CREDENTIALS * cssmCreds = NULL; CSSM_RETURN cssmRv; CSSM_DATA hashData; CSSM_DATA signatureData; CSSM_CC_HANDLE cssmSignature = 0; const SSL3Opaque* prefix; unsigned int prefixLen; SSL3Opaque prefixAndHash[SSL_MAX_DIGEST_INFO_PREFIX + HASH_LENGTH_MAX]; buf->data = NULL; status = SecKeyGetCSPHandle(key, &cspHandle); if (status != noErr) { PORT_SetError(SEC_ERROR_INVALID_KEY); goto done; } status = SecKeyGetCSSMKey(key, &cssmKey); if (status != noErr || !cssmKey) { PORT_SetError(SEC_ERROR_NO_KEY); goto done; } /* SecKeyGetBlockSize wasn't addeded until OS X 10.6 - but the * needed information is readily available on the key itself. */ signatureLen = (cssmKey->KeyHeader.LogicalKeySizeInBits + 7) / 8; if (signatureLen == 0) { PORT_SetError(SEC_ERROR_INVALID_KEY); goto done; } buf->data = (unsigned char *)PORT_Alloc(signatureLen); if (!buf->data) goto done; /* error code was set. */ sigAlg = cssmKey->KeyHeader.AlgorithmId; digestAlg = CSSM_ALGID_NONE; switch (keyType) { case rsaKey: PORT_Assert(sigAlg == CSSM_ALGID_RSA); if (ssl3_GetDigestInfoPrefix(hash->hashAlg, &prefix, &prefixLen) != SECSuccess) { goto done; } if (prefixLen + hash->len > sizeof(prefixAndHash)) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); goto done; } memcpy(prefixAndHash, prefix, prefixLen); memcpy(prefixAndHash + prefixLen, hash->u.raw, hash->len); hashData.Data = prefixAndHash; hashData.Length = prefixLen + hash->len; break; case dsaKey: case ecKey: if (keyType == ecKey) { PORT_Assert(sigAlg == CSSM_ALGID_ECDSA); doDerEncode = PR_TRUE; } else { PORT_Assert(sigAlg == CSSM_ALGID_DSA); doDerEncode = isTLS; } if (hash->hashAlg == SEC_OID_UNKNOWN) { hashData.Data = hash->u.s.sha; hashData.Length = sizeof(hash->u.s.sha); } else { hashData.Data = hash->u.raw; hashData.Length = hash->len; } break; default: PORT_SetError(SEC_ERROR_INVALID_KEY); goto done; } PRINT_BUF(60, (NULL, "hash(es) to be signed", hashData.Data, hashData.Length)); /* TODO(rsleevi): Should it be kSecCredentialTypeNoUI? In Win32, at least, * you can prevent the UI by setting the provider handle on the * certificate to be opened with CRYPT_SILENT, but is there an equivalent? */ status = SecKeyGetCredentials(key, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &cssmCreds); if (status != noErr) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, status); goto done; } signatureData.Length = signatureLen; signatureData.Data = (uint8*)buf->data; cssmRv = CSSM_CSP_CreateSignatureContext(cspHandle, sigAlg, cssmCreds, cssmKey, &cssmSignature); if (cssmRv) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, cssmRv); goto done; } /* See "Apple Cryptographic Service Provider Functional Specification" */ if (cssmKey->KeyHeader.AlgorithmId == CSSM_ALGID_RSA) { /* To set RSA blinding for RSA keys */ CSSM_CONTEXT_ATTRIBUTE blindingAttr; blindingAttr.AttributeType = CSSM_ATTRIBUTE_RSA_BLINDING; blindingAttr.AttributeLength = sizeof(uint32); blindingAttr.Attribute.Uint32 = 1; cssmRv = CSSM_UpdateContextAttributes(cssmSignature, 1, &blindingAttr); if (cssmRv) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, cssmRv); goto done; } } cssmRv = CSSM_SignData(cssmSignature, &hashData, 1, digestAlg, &signatureData); if (cssmRv) { PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, cssmRv); goto done; } buf->len = signatureData.Length; if (doDerEncode) { SECItem derSig = {siBuffer, NULL, 0}; /* This also works for an ECDSA signature */ rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len); if (rv == SECSuccess) { PORT_Free(buf->data); /* discard unencoded signature. */ *buf = derSig; /* give caller encoded signature. */ } else if (derSig.data) { PORT_Free(derSig.data); } } else { rv = SECSuccess; } PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len)); done: /* cspHandle, cssmKey, and cssmCreds are owned by the SecKeyRef and * should not be freed. When the PlatformKey is freed, they will be * released. */ if (cssmSignature) CSSM_DeleteContext(cssmSignature); if (rv != SECSuccess && buf->data) { PORT_Free(buf->data); buf->data = NULL; } return rv; }
static int kc_rsa_sign(int type, const unsigned char *from, unsigned int flen, unsigned char *to, unsigned int *tlen, const RSA *rsa) { struct kc_rsa *kc = RSA_get_app_data(rk_UNCONST(rsa)); CSSM_RETURN cret; OSStatus ret; const CSSM_ACCESS_CREDENTIALS *creds; SecKeyRef privKeyRef = kc->pkey; CSSM_CSP_HANDLE cspHandle; const CSSM_KEY *cssmKey; CSSM_CC_HANDLE sigHandle = 0; CSSM_DATA sig, in; int fret = 0; CSSM_ALGORITHMS stype; if (type == NID_md5) { stype = CSSM_ALGID_MD5; } else if (type == NID_sha1) { stype = CSSM_ALGID_SHA1; } else if (type == NID_sha256) { stype = CSSM_ALGID_SHA256; } else if (type == NID_sha384) { stype = CSSM_ALGID_SHA384; } else if (type == NID_sha512) { stype = CSSM_ALGID_SHA512; } else return -1; cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey); if(cret) heim_abort("SecKeyGetCSSMKey failed: %d", cret); cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle); if(cret) heim_abort("SecKeyGetCSPHandle failed: %d", cret); ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeNoUI, &creds); if(ret) heim_abort("SecKeyGetCredentials failed: %d", (int)ret); ret = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA, creds, cssmKey, &sigHandle); if(ret) heim_abort("CSSM_CSP_CreateSignatureContext failed: %d", (int)ret); in.Data = (uint8 *)from; in.Length = flen; sig.Data = (uint8 *)to; sig.Length = kc->keysize; cret = CSSM_SignData(sigHandle, &in, 1, stype, &sig); if(cret) { /* cssmErrorString(cret); */ fret = -1; } else { fret = 1; *tlen = (unsigned int)sig.Length; } if(sigHandle) CSSM_DeleteContext(sigHandle); return fret; }
/* sign with RSA blinging option */ static CSSM_RETURN _cspSign(CSSM_CSP_HANDLE cspHand, uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc. CSSM_KEY_PTR key, // private key const CSSM_DATA *text, CSSM_BOOL rsaBlinding, CSSM_DATA_PTR sig) // RETURNED { CSSM_CC_HANDLE sigHand; CSSM_RETURN crtn; CSSM_RETURN ocrtn = CSSM_OK; const CSSM_DATA *ptext; CSSM_DATA digest = {0, NULL}; CSSM_ALGORITHMS digestAlg = CSSM_ALGID_NONE; /* handle special cases for raw sign */ switch(algorithm) { case CSSM_ALGID_SHA1: digestAlg = CSSM_ALGID_SHA1; algorithm = CSSM_ALGID_RSA; break; case CSSM_ALGID_MD5: digestAlg = CSSM_ALGID_MD5; algorithm = CSSM_ALGID_RSA; break; case CSSM_ALGID_DSA: digestAlg = CSSM_ALGID_SHA1; algorithm = CSSM_ALGID_DSA; break; default: break; } if(digestAlg != CSSM_ALGID_NONE) { crtn = cspDigest(cspHand, digestAlg, CSSM_FALSE, // mallocDigest text, &digest); if(crtn) { return crtn; } /* sign digest with raw RSA/DSA */ ptext = &digest; } else { ptext = text; } crtn = CSSM_CSP_CreateSignatureContext(cspHand, algorithm, NULL, // passPhrase key, &sigHand); if(crtn) { printError("CSSM_CSP_CreateSignatureContext (1)", crtn); return crtn; } if(rsaBlinding) { CSSM_CONTEXT_ATTRIBUTE newAttr; newAttr.AttributeType = CSSM_ATTRIBUTE_RSA_BLINDING; newAttr.AttributeLength = sizeof(uint32); newAttr.Attribute.Uint32 = 1; crtn = CSSM_UpdateContextAttributes(sigHand, 1, &newAttr); if(crtn) { printError("CSSM_UpdateContextAttributes", crtn); return crtn; } } crtn = CSSM_SignData(sigHand, ptext, 1, digestAlg, sig); if(crtn) { printError("CSSM_SignData", crtn); ocrtn = crtn; } crtn = CSSM_DeleteContext(sigHand); if(crtn) { printError("CSSM_DeleteContext", crtn); ocrtn = crtn; } if(digest.Data != NULL) { CSSM_FREE(digest.Data); } return ocrtn; }
CryptoX_Result CryptoMac_VerifySignature(CryptoX_SignatureHandle* aInputData, CryptoX_PublicKey* aPublicKey, const unsigned char* aSignature, unsigned int aSignatureLen) { if (!aInputData || !*aInputData || !aPublicKey || !*aPublicKey || !aSignature || aSignatureLen == 0) { return CryptoX_Error; } if (!OnLionOrLater()) { if (!sCspHandle) { return CryptoX_Error; } CSSM_KEY* publicKey; OSStatus status = SecKeyGetCSSMKey((SecKeyRef)*aPublicKey, (const CSSM_KEY**)&publicKey); if (status) { return CryptoX_Error; } CSSM_CC_HANDLE ccHandle; if (CSSM_CSP_CreateSignatureContext(sCspHandle, CSSM_ALGID_SHA1WithRSA, NULL, publicKey, &ccHandle) != CSSM_OK) { return CryptoX_Error; } CryptoX_Result result = CryptoX_Error; CSSM_DATA signatureData; signatureData.Data = (uint8*)aSignature; signatureData.Length = aSignatureLen; CSSM_DATA inputData; inputData.Data = CFDataGetMutableBytePtr((CFMutableDataRef) (((CSSM_DATA_PTR)*aInputData)->Data)); inputData.Length = ((CSSM_DATA_PTR)*aInputData)->Length; if (CSSM_VerifyData(ccHandle, &inputData, 1, CSSM_ALGID_NONE, &signatureData) == CSSM_OK) { result = CryptoX_Success; } return result; } CFDataRef signatureData = CFDataCreate(kCFAllocatorDefault, aSignature, aSignatureLen); if (!signatureData) { return CryptoX_Error; } CFErrorRef error; SecTransformRef verifier = SecVerifyTransformCreatePtr((SecKeyRef)*aPublicKey, signatureData, &error); if (!verifier || error) { CFRelease(signatureData); return CryptoX_Error; } SecTransformSetAttributePtr(verifier, kSecTransformInputAttributeName, (CFDataRef)*aInputData, &error); if (error) { CFRelease(signatureData); CFRelease(verifier); return CryptoX_Error; } CryptoX_Result result = CryptoX_Error; CFTypeRef rv = SecTransformExecutePtr(verifier, &error); if (error) { CFRelease(signatureData); CFRelease(verifier); return CryptoX_Error; } if (CFGetTypeID(rv) == CFBooleanGetTypeID() && CFBooleanGetValue((CFBooleanRef)rv) == true) { result = CryptoX_Success; } CFRelease(signatureData); CFRelease(verifier); return result; }
int main(int argc, char **argv) { int arg; char *argp; unsigned oloop; unsigned iloop; CSSM_DATA ptext = {0, NULL}; CSSM_CSP_HANDLE cspHand; int i; int rtn = 0; uint32 keySizeInBits = 0; CSSM_KEY pubKey; CSSM_KEY privKey; CSSM_DATA sig = {0, NULL}; CSSM_DATA digest = {0, NULL}; CSSM_RETURN crtn; const char *digestStr; /* * User-spec'd params */ CSSM_BOOL keySizeSpec = CSSM_FALSE; unsigned oloops = OLOOPS_DEF; unsigned iloops = ILOOPS_DEF; CSSM_BOOL verbose = CSSM_FALSE; CSSM_BOOL quiet = CSSM_FALSE; unsigned pauseInterval = 0; CSSM_BOOL bareCsp = CSSM_TRUE; CSSM_ALGORITHMS rawSigAlg = CSSM_ALGID_RSA; for(arg=1; arg<argc; arg++) { argp = argv[arg]; switch(argp[0]) { case 'a': switch(argp[2]) { case 'r': rawSigAlg = CSSM_ALGID_RSA; break; case 'd': rawSigAlg = CSSM_ALGID_DSA; break; default: usage(argv); } break; case 'l': oloops = atoi(&argp[2]); break; case 'i': iloops = atoi(&argp[2]); break; case 'k': keySizeInBits = atoi(&argp[2]); keySizeSpec = CSSM_TRUE; break; case 'v': verbose = CSSM_TRUE; break; case 'D': bareCsp = CSSM_FALSE; break; case 'q': quiet = CSSM_TRUE; break; case 'p': pauseInterval = atoi(&argp[2]);; break; case 'h': default: usage(argv); } } ptext.Data = (uint8 *)CSSM_MALLOC(MAX_TEXT_SIZE); if(ptext.Data == NULL) { printf("Insufficient heap space\n"); exit(1); } /* ptext length set in inner test loop */ printf("Starting rawRsaSig; args: "); for(i=1; i<argc; i++) { printf("%s ", argv[i]); } printf("\n"); cspHand = cspDlDbStartup(bareCsp, NULL); if(cspHand == 0) { exit(1); } if(pauseInterval) { fpurge(stdin); printf("Top of test; hit CR to proceed: "); getchar(); } for(oloop=0; ; oloop++) { /* key size? */ if(!keySizeSpec) { /* random key size */ keySizeInBits = randKeySizeBits(rawSigAlg, OT_Sign); } if(!quiet) { if(verbose || ((oloop % LOOP_NOTIFY) == 0)) { printf("...oloop %d keySize %u\n", oloop, (unsigned)keySizeInBits); } } /* generate a key pair */ crtn = cspGenKeyPair(cspHand, rawSigAlg, "foo", 3, keySizeInBits, &pubKey, CSSM_TRUE, // all keys ref for speed CSSM_KEYUSE_VERIFY, CSSM_KEYBLOB_RAW_FORMAT_NONE, &privKey, CSSM_TRUE, CSSM_KEYUSE_SIGN, CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_FALSE); // genSeed not used if(crtn) { return testError(quiet); } for(iloop=0; iloop<iloops; iloop++) { CSSM_ALGORITHMS sigAlg; CSSM_ALGORITHMS digestAlg; CSSM_CC_HANDLE sigHand; /* alternate digest algs for RSA */ if(rawSigAlg == CSSM_ALGID_RSA) { if(iloop & 1) { sigAlg = CSSM_ALGID_SHA1WithRSA; digestAlg = CSSM_ALGID_SHA1; digestStr = "SHA1"; } else { sigAlg = CSSM_ALGID_MD5WithRSA; digestAlg = CSSM_ALGID_MD5; digestStr = "MD5 "; } } else { sigAlg = CSSM_ALGID_SHA1WithDSA; digestAlg = CSSM_ALGID_SHA1; digestStr = "SHA1"; } /* new plaintext each inner loop */ simpleGenData(&ptext, 1, MAX_TEXT_SIZE); if(!quiet) { if(verbose || ((iloop % LOOP_NOTIFY) == 0)) { printf(" ...iloop %d digest %s text size %lu\n", iloop, digestStr, ptext.Length); } } /*** phase 1 ***/ /* digest+sign */ crtn = cspStagedSign(cspHand, sigAlg, &privKey, &ptext, DO_MULTI_UPDATE, // multiUpdates &sig); if(crtn && testError(quiet)) { goto abort; } /* digest */ crtn = cspStagedDigest(cspHand, digestAlg, CSSM_FALSE, // mallocDigest DO_MULTI_UPDATE, // multiUpdates &ptext, &digest); if(crtn && testError(quiet)) { goto abort; } /* raw RSA/DSA verify */ crtn = CSSM_CSP_CreateSignatureContext(cspHand, rawSigAlg, NULL, // passPhrase &pubKey, &sigHand); if(crtn) { printError("CSSM_CSP_CreateSignatureContext (1)", crtn); return crtn; } crtn = CSSM_VerifyData(sigHand, &digest, 1, digestAlg, &sig); if(crtn) { printError("CSSM_VerifyData(raw RSA)", crtn); if(testError(quiet)) { goto abort; } } /* free resources - reuse the digest for raw sign */ appFreeCssmData(&sig, CSSM_FALSE); CSSM_DeleteContext(sigHand); /*** phase 2 ***/ /* raw RSA/DSA sign */ crtn = CSSM_CSP_CreateSignatureContext(cspHand, rawSigAlg, NULL, // passPhrase &privKey, &sigHand); if(crtn) { printError("CSSM_CSP_CreateSignatureContext (1)", crtn); return crtn; } crtn = CSSM_SignData(sigHand, &digest, 1, digestAlg, &sig); if(crtn) { printError("CSSM_SignData(raw RSA)", crtn); if(testError(quiet)) { goto abort; } } /* all-in-one verify */ crtn = cspStagedSigVerify(cspHand, sigAlg, &pubKey, &ptext, &sig, DO_MULTI_UPDATE, // multiUpdates CSSM_OK); if(crtn && testError(quiet)) { goto abort; } /* clean up */ appFreeCssmData(&sig, CSSM_FALSE); appFreeCssmData(&digest, CSSM_FALSE); CSSM_DeleteContext(sigHand); } /* end of inner loop */ /* free keys */ cspFreeKey(cspHand, &pubKey); cspFreeKey(cspHand, &privKey); if(oloops && (oloop == oloops)) { break; } if(pauseInterval && ((oloop % pauseInterval) == 0)) { fpurge(stdin); printf("hit CR to proceed: "); getchar(); } } abort: cspShutdown(cspHand, bareCsp); if(pauseInterval) { fpurge(stdin); printf("ModuleDetach/Unload complete; hit CR to exit: "); getchar(); } if((rtn == 0) && !quiet) { printf("%s test complete\n", argv[0]); } CSSM_FREE(ptext.Data); return rtn; }
/* * Core test routine. * -- build a cert with issuer and subject as per specified name components * -- extract inferred label * -- compare inferred label to expected value * -- if labelIsCommonName true, verify that SecCertificateCopyCommonName() yields * the same string as inferred label */ static int doTest( const char *testName, bool quiet, CSSM_CSP_HANDLE cspHand, CSSM_CL_HANDLE clHand, CSSM_KEY_PTR privKey, CSSM_KEY_PTR pubKey, /* input names - one or two */ const void *name1Val, CSSM_SIZE name1Len, CSSM_BER_TAG berTag1, const CSSM_OID *name1Oid, const void *name2Val, // optional CSSM_SIZE name2Len, CSSM_BER_TAG berTag2, const CSSM_OID *name2Oid, /* expected label */ CFStringRef expectedLabel, bool labelIsCommonName) { if(!quiet) { printf("...%s\n", testName); } /* build the subject/issuer name */ NameOid nameArray[2] = { {name1Val, name1Len, name1Oid, berTag1 }, {name2Val, name2Len, name2Oid, berTag2 } }; unsigned numNames = name2Val ? 2 : 1; CSSM_X509_NAME *name = buildX509Name(nameArray, numNames); if(name == NULL) { printf("***buildX509Name screwup\n"); return -1; } /* build the cert template */ CSSM_DATA_PTR certTemp = CB_MakeCertTemplate( clHand, 0x123456, name, name, notBefore, notAfter, pubKey, SIG_ALG, NULL, NULL, // subject/issuer UniqueID NULL, 0); // extensions if(certTemp == NULL) { printf("***CB_MakeCertTemplate screwup\n"); return -1; } /* sign the cert */ CSSM_DATA signedCert = {0, NULL}; CSSM_CC_HANDLE sigHand; CSSM_RETURN crtn = CSSM_CSP_CreateSignatureContext(cspHand, SIG_ALG, NULL, // no passphrase for now privKey, &sigHand); if(crtn) { /* should never happen */ cssmPerror("CSSM_CSP_CreateSignatureContext", crtn); return 1; } crtn = CSSM_CL_CertSign(clHand, sigHand, certTemp, // CertToBeSigned NULL, // SignScope per spec 0, // ScopeSize per spec &signedCert); if(crtn) { cssmPerror("CSSM_CL_CertSign", crtn); return 1; } CSSM_DeleteContext(sigHand); CSSM_FREE(certTemp->Data); CSSM_FREE(certTemp); /* * OK, we have a signed cert. * Turn it into a SecCertificateRef and get the inferred label. */ OSStatus ortn; SecCertificateRef certRef; ortn = SecCertificateCreateFromData(&signedCert, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &certRef); if(ortn) { cssmPerror("SecCertificateCreateFromData", ortn); return -1; } CFStringRef inferredLabel; ortn = SecCertificateInferLabel(certRef, &inferredLabel); if(ortn) { cssmPerror("SecCertificateCreateFromData", ortn); return -1; } CFComparisonResult res = CFStringCompare(inferredLabel, expectedLabel, 0); if(res != kCFCompareEqualTo) { fprintf(stderr, "*** label miscompare in test '%s' ***\n", testName); fprintf(stderr, "expected label : "); CFShow(expectedLabel); fprintf(stderr, "inferred label : "); CFShow(inferredLabel); if(writeFile(CERT_FILE_OUT, signedCert.Data, signedCert.Length)) { fprintf(stderr, "***Error writing cert to %s\n", CERT_FILE_OUT); } else { fprintf(stderr, "...write %lu bytes to %s\n", (unsigned long)signedCert.Length, CERT_FILE_OUT); } return -1; } if(labelIsCommonName) { CFStringRef commonName = NULL; ortn = SecCertificateCopyCommonName(certRef, &commonName); if(ortn) { cssmPerror("SecCertificateCopyCommonName", ortn); return -1; } res = CFStringCompare(inferredLabel, commonName, 0); if(res != kCFCompareEqualTo) { printf("*** CommonName miscompare in test '%s' ***\n", testName); printf("Common Name : '"); CFShow(commonName); printf("'\n"); printf("inferred label : '"); CFShow(inferredLabel); printf("'\n"); if(writeFile(CERT_FILE_OUT, signedCert.Data, signedCert.Length)) { printf("***Error writing cert to %s\n", CERT_FILE_OUT); } else { printf("...write %lu bytes to %s\n", (unsigned long)signedCert.Length, CERT_FILE_OUT); } return -1; } CFRelease(commonName); } CFRelease(certRef); CSSM_FREE(signedCert.Data); CB_FreeX509Name(name); CFRelease(inferredLabel); return 0; }
/* * 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); } }
/* * 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); } }