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; }
void WizInitBizCertDialog::accept() { verifyCert(); }