Example #1
0
int
CA_passive_authentication(const EAC_CTX *ctx, PKCS7 *ef_cardsecurity)
{
    X509 *ds_cert;
    X509_STORE *store;
    STACK_OF(X509) *ds_certs = NULL;
    unsigned long issuer_name_hash;
    int ret = 0;

    check(ef_cardsecurity && ctx && ctx->ca_ctx && ctx->ca_ctx->lookup_csca_cert, "Invalid arguments");

    /* Extract the DS certificates from the EF.CardSecurity */
    ds_certs = PKCS7_get0_signers(ef_cardsecurity, NULL, 0);
    check(ds_certs, "Failed to retrieve certificates from EF.CardSecurity");

    /* NOTE: The following code assumes that there is only one certificate in
     * PKCS7 structure. ds_cert is implicitly freed together with ds_certs. */
    ds_cert = sk_X509_pop(ds_certs);
    check(ds_cert, "Failed to retrieve DS certificate from EF.CardSecurity");

    /* Get the trust store with at least the csca certificate */
    issuer_name_hash = X509_issuer_name_hash(ds_cert);
    store = ctx->ca_ctx->lookup_csca_cert(issuer_name_hash);
    check (store, "Failed to retrieve CSCA truststore");

    /* Verify the signature and the certificate chain */
    ret = PKCS7_verify(ef_cardsecurity, ds_certs, store, NULL, NULL, 0);

err:
    if (ds_certs)
        sk_X509_free(ds_certs);

    return ret;
}
static VALUE
ossl_pkcs7_set_certificates(VALUE self, VALUE ary)
{
    STACK_OF(X509) *certs;
    X509 *cert;

    certs = pkcs7_get_certs(self);
    while((cert = sk_X509_pop(certs))) X509_free(cert);
    rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_certs_i, self);

    return ary;
}
Example #3
0
int X509_verify_cert(X509_STORE_CTX *ctx)
	{
	X509 *x,*xtmp,*chain_ss=NULL;
	X509_NAME *xn;
	int depth,i,ok=0;
	int num;
	int (*cb)();
	STACK_OF(X509) *sktmp=NULL;

	if (ctx->cert == NULL)
		{
		X509err(X509_F_X509_VERIFY_CERT,X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
		return -1;
		}

	cb=ctx->verify_cb;

	/* first we make sure the chain we are going to build is
	 * present and that the first entry is in place */
	if (ctx->chain == NULL)
		{
		if (	((ctx->chain=sk_X509_new_null()) == NULL) ||
			(!sk_X509_push(ctx->chain,ctx->cert)))
			{
			X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
			goto end;
			}
		CRYPTO_add(&ctx->cert->references,1,CRYPTO_LOCK_X509);
		ctx->last_untrusted=1;
		}

	/* We use a temporary STACK so we can chop and hack at it */
	if (ctx->untrusted != NULL
	    && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL)
		{
		X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
		goto end;
		}

	num=sk_X509_num(ctx->chain);
	x=sk_X509_value(ctx->chain,num-1);
	depth=ctx->depth;


	for (;;)
		{
		/* If we have enough, we break */
		if (depth < num) break; /* FIXME: If this happens, we should take
		                         * note of it and, if appropriate, use the
		                         * X509_V_ERR_CERT_CHAIN_TOO_LONG error
		                         * code later.
		                         */

		/* If we are self signed, we break */
		xn=X509_get_issuer_name(x);
		if (ctx->check_issued(ctx, x,x)) break;

		/* If we were passed a cert chain, use it first */
		if (ctx->untrusted != NULL)
			{
			xtmp=find_issuer(ctx, sktmp,x);
			if (xtmp != NULL)
				{
				if (!sk_X509_push(ctx->chain,xtmp))
					{
					X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
					goto end;
					}
				CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509);
				sk_X509_delete_ptr(sktmp,xtmp);
				ctx->last_untrusted++;
				x=xtmp;
				num++;
				/* reparse the full chain for
				 * the next one */
				continue;
				}
			}
		break;
		}

	/* at this point, chain should contain a list of untrusted
	 * certificates.  We now need to add at least one trusted one,
	 * if possible, otherwise we complain. */

	/* Examine last certificate in chain and see if it
 	 * is self signed.
 	 */

	i=sk_X509_num(ctx->chain);
	x=sk_X509_value(ctx->chain,i-1);
	xn = X509_get_subject_name(x);
	if (ctx->check_issued(ctx, x, x))
		{
		/* we have a self signed certificate */
		if (sk_X509_num(ctx->chain) == 1)
			{
			/* We have a single self signed certificate: see if
			 * we can find it in the store. We must have an exact
			 * match to avoid possible impersonation.
			 */
			ok = ctx->get_issuer(&xtmp, ctx, x);
			if ((ok <= 0) || X509_cmp(x, xtmp)) 
				{
				ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
				ctx->current_cert=x;
				ctx->error_depth=i-1;
				if (ok == 1) X509_free(xtmp);
				ok=cb(0,ctx);
				if (!ok) goto end;
				}
			else 
				{
				/* We have a match: replace certificate with store version
				 * so we get any trust settings.
				 */
				X509_free(x);
				x = xtmp;
				sk_X509_set(ctx->chain, i - 1, x);
				ctx->last_untrusted=0;
				}
			}
		else
			{
			/* extract and save self signed certificate for later use */
			chain_ss=sk_X509_pop(ctx->chain);
			ctx->last_untrusted--;
			num--;
			x=sk_X509_value(ctx->chain,num-1);
			}
		}

	/* We now lookup certs from the certificate store */
	for (;;)
		{
		/* If we have enough, we break */
		if (depth < num) break;

		/* If we are self signed, we break */
		xn=X509_get_issuer_name(x);
		if (ctx->check_issued(ctx,x,x)) break;

		ok = ctx->get_issuer(&xtmp, ctx, x);

		if (ok < 0) return ok;
		if (ok == 0) break;

		x = xtmp;
		if (!sk_X509_push(ctx->chain,x))
			{
			X509_free(xtmp);
			X509err(X509_F_X509_VERIFY_CERT,ERR_R_MALLOC_FAILURE);
			return 0;
			}
		num++;
		}

	/* we now have our chain, lets check it... */
	xn=X509_get_issuer_name(x);

	/* Is last certificate looked up self signed? */
	if (!ctx->check_issued(ctx,x,x))
		{
		if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss))
			{
			if (ctx->last_untrusted >= num)
				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
			else
				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
			ctx->current_cert=x;
			}
		else
			{

			sk_X509_push(ctx->chain,chain_ss);
			num++;
			ctx->last_untrusted=num;
			ctx->current_cert=chain_ss;
			ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
			chain_ss=NULL;
			}

		ctx->error_depth=num-1;
		ok=cb(0,ctx);
		if (!ok) goto end;
		}

	/* We have the chain complete: now we need to check its purpose */
	ok = check_chain_extensions(ctx);

	if (!ok) goto end;

	/* The chain extensions are OK: check trust */

	if (ctx->trust > 0) ok = check_trust(ctx);

	if (!ok) goto end;

	/* We may as well copy down any DSA parameters that are required */
	X509_get_pubkey_parameters(NULL,ctx->chain);

	/* Check revocation status: we do this after copying parameters
	 * because they may be needed for CRL signature verification.
	 */

	ok = ctx->check_revocation(ctx);
	if(!ok) goto end;

	/* At this point, we have a chain and just need to verify it */
	if (ctx->verify != NULL)
		ok=ctx->verify(ctx);
	else
		ok=internal_verify(ctx);
	if (0)
		{
end:
		X509_get_pubkey_parameters(NULL,ctx->chain);
		}
	if (sktmp != NULL) sk_X509_free(sktmp);
	if (chain_ss != NULL) X509_free(chain_ss);
	return ok;
	}
/*
 * Please see comment in x509_vfy_apple.h
 */
int
X509_verify_cert(X509_STORE_CTX *ctx)
{
	TEAResult		ret = kTEAResultCertNotTrusted;
	TEACertificateChainRef	inputChain = NULL;
	TEACertificateChainRef	outputChain = NULL;
	__block uint64_t	certCount = 0;
	uint64_t		certLastIndex = 0;
	uint64_t		i = 0;
	int			error = 0;
	TEAParams		params = { 0 };


	if (ctx == NULL || ctx->cert == NULL)
        return kTEAResultErrorOccured;

	/* Try OpenSSL, if we get a local certificate issue verify against trusted roots */
	ret = X509_verify_cert_orig(ctx);

	/* Verify TEA is enabled and should be used. */
	if (0 != X509_TEA_is_enabled() &&
		ret != 1 && TEA_might_correct_error(ctx->error)) {

		/* Verify that the certificate chain exists, otherwise make it. */
		if (ctx->chain == NULL && (ctx->chain = sk_X509_new_null()) == NULL) {
			TEALogDebug("Could not create the certificate chain");
			ret = kTEAResultCertNotTrusted;
			goto bail;
		}

		/* Verify chain depth */
		certLastIndex = sk_X509_num(ctx->untrusted);
		if (certLastIndex > ctx->param->depth) {
			TEALogInfo("Pruning certificate chain to %" PRIu64, certLastIndex);
			certLastIndex = ctx->param->depth;
		}

		inputChain = TEACertificateChainCreate();
		if (inputChain == NULL) {
			TEALogDebug("Certificate chain creation failed");
			goto bail;
		}

		unsigned char *asn1_cert_data = NULL;
		int asn1_cert_len = i2d_X509(ctx->cert, &asn1_cert_data);
		error = TEACertificateChainAddCert(inputChain, asn1_cert_data, asn1_cert_len);
		// TEACertificateChainAddCert made a copy of the ASN.1 data, so we get to free ours here
		OPENSSL_free(asn1_cert_data);
		if (error) {
			TEALogDebug("An error occured while inserting the certificate into the chain");
			goto bail;
		}

		for (i = 0; i < certLastIndex; ++i) {
			X509	*t = sk_X509_value(ctx->untrusted, i);

			asn1_cert_data = NULL;
			asn1_cert_len = i2d_X509(t, &asn1_cert_data);
			error = TEACertificateChainAddCert(inputChain, asn1_cert_data, asn1_cert_len);
			// TEACertificateChainAddCert made a copy of the ASN.1 data, so we get to free ours here
			OPENSSL_free(asn1_cert_data);
			if (error) {
				TEALogDebug("An error occured while inserting an untrusted certificate into the chain");
				goto bail;
			}
		}

		// We put ASN.1 encoded X509 on the CertificateChain, so we don't call TEACertificateChainSetEncodingHandler
		
		params.purpose = ctx->param->purpose;
		if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
			params.check_time = ctx->param->check_time;

		outputChain = TEAVerifyCert(inputChain, &params);

		TEACertificateChainRelease(inputChain);
		inputChain = NULL;

		if (outputChain == NULL) {
			TEALogDebug("TEAVerifyCert() returned NULL.");
			goto bail;
		}

		/* Empty the context chain */
		for (i = 0; i < sk_X509_num(ctx->chain); ++i)
			sk_X509_pop(ctx->chain);

		error = TEACertificateChainGetCerts(outputChain, ^(const TEACertificateRef cert) {
			const unsigned char	*ptr = TEACertificateGetData(cert);
			X509			*c = NULL;

			if (certCount++ > certLastIndex)
				return 0;

			c = d2i_X509(NULL, &ptr, TEACertificateGetSize(cert));
			if (c == NULL) {
				TEALogDebug("Could not parse certificate");
				return 1;
			}

			if (!sk_X509_push(ctx->chain, c)) {
				TEALogDebug("Could not insert certificate into the chain");
				return 1;
			}

			return 0;
		});
		if (error) {
			TEALogDebug("An error occured while deserializing the trusted certificate chain");
			ret = kTEAResultCertNotTrusted;
			goto bail;
		}

		TEACertificateChainRelease(outputChain);
		outputChain = NULL;

		/* Fixup context data */
		ctx->current_cert   = sk_X509_value(ctx->chain, 0);
		ctx->current_issuer = sk_X509_value(ctx->chain, sk_X509_num(ctx->chain) - 1);
		ctx->error_depth = 0;
		ctx->error = 0;
		X509_get_pubkey_parameters(NULL, ctx->chain);

		ret = kTEAResultCertTrusted;
	}
Example #5
0
/*! \brief Signs a PKI_X509_OCSP_RESP, for a simpler API use PKI_X509_OCSP_RESP_sign_tk */
int PKI_X509_OCSP_RESP_sign ( PKI_X509_OCSP_RESP *resp, 
		PKI_X509_KEYPAIR *keypair, PKI_X509_CERT *cert, 
		PKI_X509_CERT *issuer, PKI_X509_CERT_STACK * otherCerts,
		PKI_DIGEST_ALG *digest, PKI_X509_OCSP_RESPID_TYPE respidType ) {

	OCSP_RESPID *rid;
	PKI_OCSP_RESP *r = NULL;

	if (!resp || !resp->value || !keypair || !keypair->value)
	{
		PKI_ERROR(PKI_ERR_PARAM_NULL, NULL);
		return PKI_ERR;
	}

	// Let's get the value
	r = resp->value;

	//
	if (!r->resp)
	{
		PKI_ERROR(PKI_ERR_PARAM_NULL, NULL);
		return PKI_ERR;
	}

	// If there is no bs, no need to sign the response
	// we do not consider this to be an error
	if (!r->bs)
	{
		PKI_ERROR(PKI_ERR_PARAM_NULL, NULL);
		return PKI_ERR;
	}

	// Checks the certificates
	if (!cert || !cert->value )
	{
		PKI_log(PKI_LOG_WARNING,"Signing an OCSP_RESP without a cert");
	}

	if (!issuer || !issuer->value )
	{
		PKI_log( PKI_LOG_WARNING, "Signing an OCSP_RESP without the "
			"issuer's certificate!");
	}

	// Let's get the responderId
	rid = r->bs->tbsResponseData->responderId;

	// Sets the responderId
	if (cert && respidType == PKI_X509_OCSP_RESPID_TYPE_BY_NAME)
	{
		if (!cert) {
			PKI_log_err("PKI_OCSP_RESPID_TYPE_BY_NAME requires signer's certificate");
			return PKI_ERR;
		}

		if (!X509_NAME_set(&rid->value.byName, X509_get_subject_name(cert->value)))
		{
			PKI_log_err("Internal Error");
			return PKI_ERR;
		}

		rid->type = V_OCSP_RESPID_NAME;
	}
	else
	{
		PKI_DIGEST *dgst = PKI_X509_KEYPAIR_pub_digest(keypair, PKI_DIGEST_ALG_SHA1);

		if (!dgst)
		{
			PKI_log_err("Can not get Keypair Sha-1 value!");
			return PKI_ERR;
		}

		rid->type = V_OCSP_RESPID_KEY;
		if((rid->value.byKey = ASN1_OCTET_STRING_new()) == NULL)
		{
			PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL);
			PKI_DIGEST_free(dgst);
			return PKI_ERR;
		}

		if(!ASN1_OCTET_STRING_set(rid->value.byKey, dgst->digest, (int) dgst->size))
		{
			PKI_log_err("Can not assign Responder Id by Key (Internal Error!)");
			PKI_DIGEST_free(dgst);
			return PKI_ERR;
		}

		// All done here.
		PKI_DIGEST_free(dgst);
	}

	if(X509_gmtime_adj(r->bs->tbsResponseData->producedAt, 0) == 0)
	{
		PKI_log_err("Error adding signed time to response");
	}

	if (!(r->resp->responseBytes = OCSP_RESPBYTES_new()))
	{
		PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL);
		return PKI_ERR;
	}

	if((r->resp->responseBytes->responseType = 
			OBJ_nid2obj(NID_id_pkix_OCSP_basic)) == NULL )
	{
		PKI_log_debug("id-pkix-ocsp-basic OID error");
		return PKI_ERR;
	}

	/* If there's old certs, let's clean the stack */
	if( r->bs->certs )
	{
		PKI_X509_CERT_VALUE *tmp_cert = NULL;
		while ( (tmp_cert = sk_X509_pop( r->bs->certs )) != NULL )
		{
			X509_free ( tmp_cert );
		}
	}
	else
	{
		if((r->bs->certs = sk_X509_new_null()) == NULL)
		{
			PKI_log_debug("ERROR, Can not Create stack of certs in signature!");
			return( PKI_ERR );
		}
	}

	/* Let's push the signer's certificate */
	if ( cert ) OCSP_basic_add1_cert(r->bs, cert->value);

	// Let's now perform the real signing operation
	return PKI_X509_OCSP_RESP_DATA_sign(resp, keypair, digest);

}