static CSSM_RETURN tpIssuerCertViaNet( const CSSM_DATA &url, CSSM_CL_HANDLE clHand, CSSM_CSP_HANDLE cspHand, const char *verifyTime, TPCertInfo &subject, TPCertInfo *&rtnCert) { TPCertInfo *issuer = NULL; CSSM_DATA certData; CSSM_RETURN crtn; Allocator &alloc = Allocator::standard(); crtn = tpFetchViaNet(url, NULL, LT_Cert, NULL, alloc, certData); if(crtn) { tpErrorLog("tpIssuerCertViaNet: net fetch failed\n"); return CSSMERR_APPLETP_CERT_NOT_FOUND_FROM_ISSUER; } try { issuer = new TPCertInfo(clHand, cspHand, &certData, TIC_CopyData, verifyTime); } catch(...) { tpErrorLog("tpIssuerCertViaNet: bad cert via net fetch\n"); alloc.free(certData.Data); rtnCert = NULL; return CSSMERR_APPLETP_BAD_CERT_FROM_ISSUER; } alloc.free(certData.Data); /* subject/issuer match? */ if(!issuer->isIssuerOf(subject)) { tpErrorLog("tpIssuerCertViaNet: wrong issuer cert via net fetch\n"); crtn = CSSMERR_APPLETP_BAD_CERT_FROM_ISSUER; } else { /* yep, do a sig verify */ crtn = subject.verifyWithIssuer(issuer); if(crtn) { tpErrorLog("tpIssuerCertViaNet: sig verify fail for cert via net " "fetch\n"); crtn = CSSMERR_APPLETP_BAD_CERT_FROM_ISSUER; } } if(crtn) { assert(issuer != NULL); delete issuer; issuer = NULL; } rtnCert = issuer; return crtn; }
/* * Following a CSSMOID_ECDSA_WithSpecified algorithm is an encoded * ECDSA_SigAlgParams containing the digest agorithm OID. Decode and return * a unified ECDSA/digest alg (e.g. CSSM_ALGID_SHA512WithECDSA). * Returns nonzero on error. */ int decodeECDSA_SigAlgParams( const CSSM_DATA *params, CSSM_ALGORITHMS *cssmAlg) /* RETURNED */ { SecAsn1CoderRef coder = NULL; if(SecAsn1CoderCreate(&coder)) { tpErrorLog("***Error in SecAsn1CoderCreate()\n"); return -1; } CSSM_X509_ALGORITHM_IDENTIFIER algParams; memset(&algParams, 0, sizeof(algParams)); int ourRtn = 0; bool algFound = false; if(SecAsn1DecodeData(coder, params, kSecAsn1AlgorithmIDTemplate, &algParams)) { tpErrorLog("***Error decoding CSSM_X509_ALGORITHM_IDENTIFIER\n"); ourRtn = -1; goto errOut; } CSSM_ALGORITHMS digestAlg; algFound = cssmOidToAlg(&algParams.algorithm, &digestAlg); if(!algFound) { tpErrorLog("***Unknown algorithm in CSSM_X509_ALGORITHM_IDENTIFIER\n"); ourRtn = -1; goto errOut; } switch(digestAlg) { case CSSM_ALGID_SHA1: *cssmAlg = CSSM_ALGID_SHA1WithECDSA; break; case CSSM_ALGID_SHA224: *cssmAlg = CSSM_ALGID_SHA224WithECDSA; break; case CSSM_ALGID_SHA256: *cssmAlg = CSSM_ALGID_SHA256WithECDSA; break; case CSSM_ALGID_SHA384: *cssmAlg = CSSM_ALGID_SHA384WithECDSA; break; case CSSM_ALGID_SHA512: *cssmAlg = CSSM_ALGID_SHA512WithECDSA; break; default: tpErrorLog("***Unknown algorithm in ECDSA_SigAlgParams\n"); ourRtn = -1; } errOut: SecAsn1CoderRelease(coder); return ourRtn; }
/* * Free memory via specified plugin's app-level allocator */ void tpFreePluginMemory( CSSM_HANDLE hand, void *p) { CSSM_API_MEMORY_FUNCS memFuncs; CSSM_RETURN crtn = CSSM_GetAPIMemoryFunctions(hand, &memFuncs); if(crtn) { tpErrorLog("CSSM_GetAPIMemoryFunctions failure\n"); /* oh well, leak and continue */ return; } memFuncs.free_func(p, memFuncs.AllocRef); }
/* * Obtain signature algorithm info from a cert. */ CSSM_X509_ALGORITHM_IDENTIFIER_PTR tp_CertGetAlgId( TPCertInfo *cert, CSSM_DATA_PTR *valueToFree) // used in tp_CertFreeAlgId { CSSM_RETURN crtn; CSSM_DATA_PTR val; *valueToFree = NULL; crtn = cert->fetchField(&CSSMOID_X509V1SignatureAlgorithm, &val); if(crtn) { tpErrorLog("Error on fetchField(CSSMOID_X509V1SignatureAlgorithm)\n"); return NULL; } *valueToFree = val; return (CSSM_X509_ALGORITHM_IDENTIFIER_PTR)val->Data; }
/* * Obtain the public key blob from a cert. */ CSSM_DATA_PTR tp_CertGetPublicKey( TPCertInfo *cert, CSSM_DATA_PTR *valueToFree) // used in tp_CertFreePublicKey { CSSM_RETURN crtn; CSSM_DATA_PTR val; CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *keyInfo; *valueToFree = NULL; crtn = cert->fetchField(&CSSMOID_X509V1SubjectPublicKeyCStruct, &val); if(crtn) { tpErrorLog("Error on CSSM_CL_CertGetFirstFieldValue(PublicKeyCStruct)\n"); return NULL; } *valueToFree = val; keyInfo = (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)val->Data; return &keyInfo->subjectPublicKey; }
/* * Fetch CRL(s) from specified cert if the cert has a cRlDistributionPoint * extension. * * Return values: * CSSM_OK - found and returned fully verified CRL * CSSMERR_APPLETP_CRL_NOT_FOUND - no CRL in cRlDistributionPoint * Anything else - gross error, typically from last LDAP/HTTP attempt * * FIXME - this whole mechanism sort of falls apart if verifyContext.verifyTime * is non-NULL. How are we supposed to get the CRL which was valid at * a specified time in the past? */ CSSM_RETURN tpFetchCrlFromNet( TPCertInfo &cert, TPVerifyContext &vfyCtx, TPCrlInfo *&crl) // RETURNED { /* does the cert have a cRlDistributionPoint? */ CSSM_DATA_PTR fieldValue; // mallocd by CL CSSM_RETURN crtn = cert.fetchField(&CSSMOID_CrlDistributionPoints, &fieldValue); switch(crtn) { case CSSM_OK: break; case CSSMERR_CL_NO_FIELD_VALUES: /* field not present */ return CSSMERR_APPLETP_CRL_NOT_FOUND; default: /* gross error */ return crtn; } if(fieldValue->Length != sizeof(CSSM_X509_EXTENSION)) { tpErrorLog("tpFetchCrlFromNet: malformed CSSM_FIELD"); return CSSMERR_TP_UNKNOWN_FORMAT; } CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)fieldValue->Data; CE_CRLDistPointsSyntax *dps = (CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue; TPCrlInfo *rtnCrl = NULL; /* default return if we don't find anything */ crtn = CSSMERR_APPLETP_CRL_NOT_FOUND; for(unsigned dex=0; dex<dps->numDistPoints; dex++) { CE_CRLDistributionPoint *dp = &dps->distPoints[dex]; if(dp->distPointName == NULL) { continue; } /* * FIXME if this uses an indirect CRL, we need to follow the * crlIssuer field... TBD. */ switch(dp->distPointName->nameType) { case CE_CDNT_NameRelativeToCrlIssuer: /* not yet */ tpErrorLog("tpFetchCrlFromNet: " "CE_CDNT_NameRelativeToCrlIssuer not implemented\n"); break; case CE_CDNT_FullName: { /* * Since we don't support indirect CRLs (yet), we always pass * the cert-to-be-verified's issuer as the CRL issuer for * cache lookup. */ CE_GeneralNames *names = dp->distPointName->dpn.fullName; crtn = tpFetchViaGeneralNames(names, cert, cert.issuerName(), &vfyCtx, 0, // clHand, use the one in vfyCtx 0, // cspHand, ditto vfyCtx.verifyTime, NULL, &rtnCrl); break; } /* CE_CDNT_FullName */ default: /* not yet */ tpErrorLog("tpFetchCrlFromNet: " "unknown distPointName->nameType (%u)\n", (unsigned)dp->distPointName->nameType); break; } /* switch distPointName->nameType */ if(crtn == CSSM_OK) { /* i.e., tpFetchViaGeneralNames SUCCEEDED */ break; } } /* for each distPoints */ cert.freeField(&CSSMOID_CrlDistributionPoints, fieldValue); if(crtn == CSSM_OK) { assert(rtnCrl != NULL); crl = rtnCrl; } return crtn; }
static CSSM_DB_UNIQUE_RECORD_PTR tpCrlLookup( CSSM_DL_DB_HANDLE dlDb, const CSSM_DATA *issuerName, // DER-encoded CSSM_TIMESTRING verifyTime, // may be NULL, implies "now" CSSM_HANDLE_PTR resultHand, // RETURNED CSSM_DATA_PTR crl) // RETURNED { CSSM_QUERY query; CSSM_SELECTION_PREDICATE pred[3]; CSSM_DB_UNIQUE_RECORD_PTR record = NULL; char timeStr[CSSM_TIME_STRLEN + 1]; crl->Data = NULL; crl->Length = 0; /* Three predicates...first, the issuer name */ pred[0].DbOperator = CSSM_DB_EQUAL; pred[0].Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; pred[0].Attribute.Info.Label.AttributeName = (char*) "Issuer"; pred[0].Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; pred[0].Attribute.Value = const_cast<CSSM_DATA_PTR>(issuerName); pred[0].Attribute.NumberOfValues = 1; /* now before/after. Cook up an appropriate time string. */ if(verifyTime != NULL) { /* Caller spec'd tolerate any format */ int rtn = tpTimeToCssmTimestring(verifyTime, (unsigned)strlen(verifyTime), timeStr); if(rtn) { tpErrorLog("tpCrlLookup: Invalid VerifyTime string\n"); return NULL; } } else { /* right now */ StLock<Mutex> _(tpTimeLock()); timeAtNowPlus(0, TIME_CSSM, timeStr); } CSSM_DATA timeData; timeData.Data = (uint8 *)timeStr; timeData.Length = CSSM_TIME_STRLEN; #if SEARCH_BY_DATE pred[1].DbOperator = CSSM_DB_LESS_THAN; pred[1].Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; pred[1].Attribute.Info.Label.AttributeName = (char*) "NextUpdate"; pred[1].Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; pred[1].Attribute.Value = &timeData; pred[1].Attribute.NumberOfValues = 1; pred[2].DbOperator = CSSM_DB_GREATER_THAN; pred[2].Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; pred[2].Attribute.Info.Label.AttributeName = (char*) "ThisUpdate"; pred[2].Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; pred[2].Attribute.Value = &timeData; pred[2].Attribute.NumberOfValues = 1; #endif query.RecordType = CSSM_DL_DB_RECORD_X509_CRL; query.Conjunctive = CSSM_DB_AND; #if SEARCH_BY_DATE query.NumSelectionPredicates = 3; #else query.NumSelectionPredicates = 1; #endif query.SelectionPredicate = pred; query.QueryLimits.TimeLimit = 0; // FIXME - meaningful? query.QueryLimits.SizeLimit = 1; // FIXME - meaningful? query.QueryFlags = 0; // FIXME - used? CSSM_DL_DataGetFirst(dlDb, &query, resultHand, NULL, // don't fetch attributes crl, &record); return record; }