예제 #1
0
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;
}
예제 #6
0
/*
 * 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;
}