static int checkOneField( CSSM_CL_HANDLE clHand, CSSM_HANDLE cacheHand1, CSSM_HANDLE cacheHand2, const CSSM_OID *fieldOid) { CSSM_DATA_PTR fieldData1 = NULL; CSSM_DATA_PTR fieldData2 = NULL; CSSM_RETURN crtn; CSSM_HANDLE resultHand1 = 0; CSSM_HANDLE resultHand2 = 0; uint32 numFields = 0; int rtn; crtn = CSSM_CL_CertGetFirstCachedFieldValue( clHand, cacheHand1, fieldOid, &resultHand1, &numFields, &fieldData1); if(crtn) { return crtn; } if(numFields != 1) { printf("Fiedl not present; try another cert\n"); return 1; } crtn = CSSM_CL_CertGetFirstCachedFieldValue( clHand, cacheHand2, fieldOid, &resultHand2, &numFields, &fieldData2); if(crtn) { return crtn; } rtn = compareFields(fieldOid, fieldData1, fieldData2); CSSM_CL_CertAbortQuery(clHand, resultHand1); CSSM_CL_CertAbortQuery(clHand, resultHand2); CSSM_CL_FreeFieldValue(clHand, fieldOid, fieldData1); CSSM_CL_FreeFieldValue(clHand, fieldOid, fieldData2); return rtn; }
/* * Obtain atrbitrary field from cached cert. This class takes care of freeing * the field in its destructor. * * Returns NULL if field not found (not exception). * * Caller optionally specifies field length to check - specifying zero means * "don't care, don't check". Actual field length always returned in fieldLength. */ const void *CertParser::fieldForOid( const CSSM_OID &oid, CSSM_SIZE &fieldLength) // IN/OUT { CSSM_RETURN crtn; uint32 NumberOfFields = 0; CSSM_HANDLE resultHand = 0; CSSM_DATA_PTR fieldData = NULL; assert(mClHand != 0); assert(mCacheHand != 0); crtn = CSSM_CL_CertGetFirstCachedFieldValue( mClHand, mCacheHand, &oid, &resultHand, &NumberOfFields, &fieldData); if(crtn) { /* not an error; just means that the cert doesn't have this field */ return NULL; } assert(NumberOfFields == 1); CSSM_CL_CertAbortQuery(mClHand, resultHand); if(fieldLength) { if(fieldLength != fieldData->Length) { /* FIXME what's a good way to log in this situation? */ printf("***CertParser::fieldForOid: field length mismatch\n"); return NULL; } } /* Store the OID and the field for autorelease */ CP_FetchedField *cpField = new CP_FetchedField(oid, fieldData, mClHand); mFetchedFields.push_back(cpField); fieldLength = fieldData->Length; return fieldData->Data; }
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; }