+++ /dev/null
-/*
- * certLabelTest.cpp - test SecCertificateInferLabel(), in particular, Radar
- * 3529689 (teletex strings) and 4746055 (add Description
- * in parentheses)
- */
-
-#include <stdlib.h>
-#include <strings.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <Security/Security.h>
-#include <Security/SecCertificatePriv.h>
-#include <clAppUtils/clutils.h>
-#include <clAppUtils/CertBuilderApp.h>
-#include <utilLib/common.h>
-#include <utilLib/cspwrap.h>
-#include <security_cdsa_utils/cuFileIo.h>
-
-static void usage(char **argv)
-{
- printf("usage: %s [options]\n", argv[0]);
- printf("Options:\n");
- printf(" -p -- pause for leaks check\n");
- printf(" -q -- quiet\n");
- /* etc. */
- exit(1);
-}
-
-#define KEY_SIZE 1024
-#define KEY_ALG CSSM_ALGID_RSA
-#define SIG_ALG CSSM_ALGID_SHA1WithRSA
-#define CERT_FILE_OUT "/tmp/certLabelTest.cer"
-
-/*
- * Here's the definitive string for Radar 3529689.
- * BER tag = Teletex/T61, encoding = kCFStringEncodingISOLatin1.
- * I hope Herr Petersen does not mind.
- */
-static const unsigned char JurgenPetersen[] =
-{
- 0x4a, 0xf8, 0x72, 0x67, 0x65, 0x6e, 0x20, 0x4e,
- 0xf8, 0x72, 0x67, 0x61, 0x61, 0x72, 0x64, 0x20,
- 0x50, 0x65, 0x74, 0x65, 0x72, 0x73, 0x65, 0x6e
-};
-
-/*
- * Name/OID pair used in buildX509Name().
- * This logic is like the CB_BuildX509Name() code in clAppUtils/CertBuilderApp.cpp,
- * with the addition of the berTag specification, and data is specified as a void *
- * and size_t.
- */
-typedef struct {
- const void *nameVal;
- CSSM_SIZE nameLen;
- const CSSM_OID *oid;
- CSSM_BER_TAG berTag;
-} NameOid;
-
-/*
- * Build up a CSSM_X509_NAME from an arbitrary list of name/OID/tag triplets.
- * We do one a/v pair per RDN.
- */
-static CSSM_X509_NAME *buildX509Name(
- const 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 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 = nameOid->berTag;
- atvp->value.Length = nameOid->nameLen;
- atvp->value.Data = (uint8 *)CSSM_MALLOC(nameOid->nameLen);
- memmove(atvp->value.Data, nameOid->nameVal, nameOid->nameLen);
- }
- return top;
-}
-
-/* just make these static and reuse them */
-static CSSM_X509_TIME *notBefore;
-static CSSM_X509_TIME *notAfter;
-
-/*
- * 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;
-}
-
-int main(int argc, char **argv)
-{
- bool quiet = false;
- bool doPause = false;
-
- int arg;
- while ((arg = getopt(argc, argv, "pqh")) != -1) {
- switch (arg) {
- case 'q':
- quiet = true;
- break;
- case 'p':
- doPause = true;
- break;
- case 'h':
- usage(argv);
- }
- }
- if(optind != argc) {
- usage(argv);
- }
-
- testStartBanner("certLabelTest", argc, argv);
-
- CSSM_CL_HANDLE clHand = clStartup();
- CSSM_CSP_HANDLE cspHand = cspStartup();
-
- /* create a key pair */
- CSSM_RETURN crtn;
- CSSM_KEY pubKey;
- CSSM_KEY privKey;
-
- crtn = cspGenKeyPair(cspHand, KEY_ALG,
- "someLabel", 8,
- KEY_SIZE,
- &pubKey, CSSM_FALSE, CSSM_KEYUSE_ANY, CSSM_KEYBLOB_RAW_FORMAT_NONE,
- &privKey, CSSM_FALSE, CSSM_KEYUSE_ANY, CSSM_KEYBLOB_RAW_FORMAT_NONE,
- CSSM_FALSE);
- if(crtn) {
- printf("***Error generating RSA key pair. Aborting.\n");
- exit(1);
- }
-
- /* common params, reused for each test */
- notBefore = CB_BuildX509Time(0);
- notAfter = CB_BuildX509Time(100000);
-
- /*
- * Grind thru test cases.
- */
- int ourRtn;
-
- /* very basic */
- ourRtn = doTest("simple ASCII common name", quiet,
- cspHand, clHand, &privKey, &pubKey,
- "Simple Name", strlen("Simple Name"), BER_TAG_PRINTABLE_STRING, &CSSMOID_CommonName,
- NULL, 0, BER_TAG_UNKNOWN, NULL,
- CFSTR("Simple Name"), true);
- if(ourRtn) {
- exit(1);
- }
-
- /* test concatentation of description */
- ourRtn = doTest("ASCII common name plus ASCII description", quiet,
- cspHand, clHand, &privKey, &pubKey,
- "Simple Name", strlen("Simple Name"), BER_TAG_PRINTABLE_STRING, &CSSMOID_CommonName,
- "Description", strlen("Description"), BER_TAG_PRINTABLE_STRING, &CSSMOID_Description,
- CFSTR("Simple Name (Description)"), false);
- if(ourRtn) {
- exit(1);
- }
-
- /* basic, specifying UTF8 (should be same as PRINTABLE) */
- ourRtn = doTest("simple UTF8 common name", quiet,
- cspHand, clHand, &privKey, &pubKey,
- "Simple Name", strlen("Simple Name"), BER_TAG_PKIX_UTF8_STRING, &CSSMOID_CommonName,
- NULL, 0, BER_TAG_UNKNOWN, NULL,
- CFSTR("Simple Name"), true);
- if(ourRtn) {
- exit(1);
- }
-
- /* label from org name instead of common name */
- ourRtn = doTest("label from OrgName", quiet,
- cspHand, clHand, &privKey, &pubKey,
- "Simple Name", strlen("Simple Name"), BER_TAG_PRINTABLE_STRING, &CSSMOID_OrganizationName,
- NULL, 0, BER_TAG_UNKNOWN, NULL,
- CFSTR("Simple Name"), false);
- if(ourRtn) {
- exit(1);
- }
-
- /* label from orgUnit name instead of common name */
- ourRtn = doTest("label from OrgUnit", quiet,
- cspHand, clHand, &privKey, &pubKey,
- "Simple Name", strlen("Simple Name"), BER_TAG_PRINTABLE_STRING, &CSSMOID_OrganizationalUnitName,
- NULL, 0, BER_TAG_UNKNOWN, NULL,
- CFSTR("Simple Name"), false);
- if(ourRtn) {
- exit(1);
- }
-
- /* label from orgUnit name, description is ignored (it's only used if the
- * label comes from CommonName) */
- ourRtn = doTest("label from OrgUnit, description is ignored", quiet,
- cspHand, clHand, &privKey, &pubKey,
- "Simple Name", strlen("Simple Name"), BER_TAG_PRINTABLE_STRING, &CSSMOID_OrganizationalUnitName,
- "Description", strlen("Description"), BER_TAG_PRINTABLE_STRING, &CSSMOID_Description,
- CFSTR("Simple Name"), false);
- if(ourRtn) {
- exit(1);
- }
-
- /* Radar 3529689: T61/Teletex, ISOLatin encoding, commonName only */
- CFStringRef t61Str = CFStringCreateWithBytes(NULL, JurgenPetersen, sizeof(JurgenPetersen),
- kCFStringEncodingISOLatin1, true);
- ourRtn = doTest("T61/Teletex name from Radar 3529689", quiet,
- cspHand, clHand, &privKey, &pubKey,
- JurgenPetersen, sizeof(JurgenPetersen), BER_TAG_TELETEX_STRING, &CSSMOID_CommonName,
- NULL, 0, BER_TAG_UNKNOWN, NULL,
- t61Str, true);
- if(ourRtn) {
- exit(1);
- }
-
- /* Now convert that ISOLatin into Unicode and try with that */
- CFDataRef unicodeStr = CFStringCreateExternalRepresentation(NULL, t61Str,
- kCFStringEncodingUnicode, 0);
- if(unicodeStr == NULL) {
- printf("***Error converting to Unicode\n");
- exit(1);
- }
- ourRtn = doTest("Unicode CommonName", quiet,
- cspHand, clHand, &privKey, &pubKey,
- CFDataGetBytePtr(unicodeStr), CFDataGetLength(unicodeStr),
- BER_TAG_PKIX_BMP_STRING, &CSSMOID_CommonName,
- NULL, 0, BER_TAG_UNKNOWN, NULL,
- t61Str, true);
- if(ourRtn) {
- exit(1);
- }
- CFRelease(unicodeStr);
-
- /* Mix up ISOLatin Common Name and ASCII Description to ensure that the encodings
- * of the two components are handled separately */
- CFMutableStringRef combo = CFStringCreateMutable(NULL, 0);
- CFStringAppend(combo, t61Str);
- CFStringAppendCString(combo, " (Description)", kCFStringEncodingASCII);
- ourRtn = doTest("ISOLatin Common Name and ASCII Description", quiet,
- cspHand, clHand, &privKey, &pubKey,
- JurgenPetersen, sizeof(JurgenPetersen), BER_TAG_TELETEX_STRING, &CSSMOID_CommonName,
- "Description", strlen("Description"), BER_TAG_PRINTABLE_STRING, &CSSMOID_Description,
- combo, false);
- if(ourRtn) {
- exit(1);
- }
- CFRelease(combo);
- CFRelease(t61Str);
-
- if(doPause) {
- fpurge(stdin);
- printf("Pausing for leaks testing; CR to continue: ");
- getchar();
- }
- if(!quiet) {
- printf("...success\n");
- }
- return 0;
-}