int main(int argc, char **argv) { CSSM_CL_HANDLE clHand; // CL handle CSSM_DATA rawCert = {0, NULL}; uint32 numFields; CSSM_HANDLE ResultsHandle = 0; char baseName[255]; char blobName[255]; char *cp; int rtn; int nameLen; CSSM_RETURN crtn; CSSM_DATA_PTR value; CSSM_KEY_PTR key; uint32 keySize; NSS_Certificate signedCert; SecAsn1CoderRef coder; if(argc != 2) { printf("usage: %s certFile\n", argv[0]); exit(1); } /* connect to CL */ clHand = clStartup(); if(clHand == 0) { printf("clStartup failure; aborting\n"); return 0; } /* subsequent errors to abort: */ /* read a in raw cert */ unsigned len; rtn = readFile(argv[1], &rawCert.Data, &len); if(rtn) { printf("Error %s reading file %s\n", strerror(rtn), argv[1]); exit(1); } rawCert.Length = len; /* C string of file name, terminating at '.' or space */ nameLen = strlen(argv[1]); memmove(baseName, argv[1], nameLen); baseName[nameLen] = '\0'; cp = strchr(baseName, '.'); if(cp) { *cp = '\0'; } cp = strchr(baseName, ' '); if(cp) { *cp = '\0'; } /* print filename and parsed subject name as comment */ crtn = CSSM_CL_CertGetFirstFieldValue( clHand, &rawCert, &CSSMOID_X509V1SubjectNameCStruct, &ResultsHandle, &numFields, &value); if(crtn) { printError("CSSM_CL_CertGetFirstFieldValue(CSSMOID_X509V1SubjectNameCStruct)", crtn); goto abort; } CSSM_CL_CertAbortQuery(clHand, ResultsHandle); if(value == NULL) { printf("Error extracting subject name\n"); goto abort; } printHeader(argv[1], value); CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1SubjectNameCStruct, value); /* print normalized & encoded subject name as C data */ crtn = CSSM_CL_CertGetFirstFieldValue( clHand, &rawCert, &SUBJECT_NAME_OID, &ResultsHandle, &numFields, &value); if(crtn) { printError("CSSM_CL_CertGetFirstFieldValue(CSSMOID_X509V1SubjectName)", crtn); goto abort; } CSSM_CL_CertAbortQuery(clHand, ResultsHandle); if(value == NULL) { printf("Error extracting subject name\n"); goto abort; } sprintf(blobName, "%s_subject", baseName); dumpDataBlob(blobName, value); #if WRITE_NAME_FILE writeFile(blobName, value->Data, (unsigned)value->Length); #endif CSSM_CL_FreeFieldValue(clHand, &SUBJECT_NAME_OID, value); /* print key blob as data */ crtn = CSSM_CL_CertGetFirstFieldValue( clHand, &rawCert, &CSSMOID_CSSMKeyStruct, &ResultsHandle, &numFields, &value); if(crtn) { printError("CSSM_CL_CertGetFirstFieldValue(CSSMOID_CSSMKeyStruct)", crtn); goto abort; } CSSM_CL_CertAbortQuery(clHand, ResultsHandle ); if(value == NULL) { printf("Error extracting public key\n"); goto abort; } if(value->Length != sizeof(CSSM_KEY)) { printf("CSSMOID_CSSMKeyStruct length error\n"); goto abort; } key = (CSSM_KEY_PTR)value->Data; sprintf(blobName, "%s_pubKey", baseName); dumpDataBlob(blobName, &key->KeyData); keySize = key->KeyHeader.LogicalKeySizeInBits; CSSM_CL_FreeFieldValue(clHand, &CSSMOID_CSSMKeyStruct, value); /* unnormalized DER-encoded issuer */ SecAsn1CoderCreate(&coder); memset(&signedCert, 0, sizeof(signedCert)); if(SecAsn1DecodeData(coder, &rawCert, kSecAsn1SignedCertTemplate, &signedCert)) { printf("***Error NSS-decoding certificate\n"); } else { sprintf(blobName, "%s_derIssuer", baseName); dumpDataBlob(blobName, &signedCert.tbs.derIssuer); } /* now the the struct containing all three */ printf("\n { &%s_subject, &%s_pubKey, %u },\n", baseName, baseName, (unsigned)keySize); abort: free(rawCert.Data); if(clHand != 0) { CSSM_ModuleDetach(clHand); } SecAsn1CoderRelease(coder); return 0; }
// Extract the issuer and serial number from a certificate SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef cert) { OSStatus status; SecCmsIssuerAndSN *certIssuerAndSN; CSSM_CL_HANDLE clHandle; CSSM_DATA_PTR serialNumber = 0; CSSM_DATA_PTR issuer = 0; CSSM_DATA certData = {}; CSSM_HANDLE resultsHandle = 0; uint32 numberOfFields = 0; CSSM_RETURN result; void *mark; mark = PORT_ArenaMark(pl); status = SecCertificateGetCLHandle(cert, &clHandle); if (status) goto loser; status = SecCertificateGetData(cert, &certData); if (status) goto loser; /* Get the issuer from the cert. */ result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &OID_X509V1IssuerNameStd, &resultsHandle, &numberOfFields, &issuer); if (result || numberOfFields < 1) goto loser; result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle); if (result) goto loser; /* Get the serialNumber from the cert. */ result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &CSSMOID_X509V1SerialNumber, &resultsHandle, &numberOfFields, &serialNumber); if (result || numberOfFields < 1) goto loser; result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle); if (result) goto loser; /* Allocate the SecCmsIssuerAndSN struct. */ certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN)); if (certIssuerAndSN == NULL) goto loser; /* Copy the issuer. */ certIssuerAndSN->derIssuer.Data = (uint8 *) PORT_ArenaAlloc(pl, issuer->Length); if (!certIssuerAndSN->derIssuer.Data) goto loser; PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer->Data, issuer->Length); certIssuerAndSN->derIssuer.Length = issuer->Length; /* Copy the serialNumber. */ certIssuerAndSN->serialNumber.Data = (uint8 *) PORT_ArenaAlloc(pl, serialNumber->Length); if (!certIssuerAndSN->serialNumber.Data) goto loser; PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber->Data, serialNumber->Length); certIssuerAndSN->serialNumber.Length = serialNumber->Length; PORT_ArenaUnmark(pl, mark); CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber); CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer); return certIssuerAndSN; loser: PORT_ArenaRelease(pl, mark); if (serialNumber) CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber); if (issuer) CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer); PORT_SetError(SEC_INTERNAL_ONLY); return NULL; }