示例#1
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);

}
示例#2
0
s2n_cert_validation_code s2n_x509_validator_validate_cert_stapled_ocsp_response(struct s2n_x509_validator *validator,
                                                                                struct s2n_connection *conn,
                                                                                const uint8_t *ocsp_response_raw,
                                                                                uint32_t ocsp_response_length) {

    if (validator->skip_cert_validation || !validator->check_stapled_ocsp) {
        return S2N_CERT_OK;
    }

#if !S2N_OCSP_STAPLING_SUPPORTED
    /* Default to safety */
    return S2N_CERT_ERR_UNTRUSTED;
#else

    OCSP_RESPONSE *ocsp_response = NULL;
    OCSP_BASICRESP *basic_response = NULL;

    s2n_cert_validation_code ret_val = S2N_CERT_ERR_INVALID;

    if (!ocsp_response_raw) {
        return ret_val;
    }

    ocsp_response = d2i_OCSP_RESPONSE(NULL, &ocsp_response_raw, ocsp_response_length);

    if (!ocsp_response) {
        goto clean_up;
    }

    int ocsp_status = OCSP_response_status(ocsp_response);

    if (ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
        goto clean_up;
    }

    basic_response = OCSP_response_get1_basic(ocsp_response);
    if (!basic_response) {
        goto clean_up;
    }

    int i;

    int certs_in_chain = sk_X509_num(validator->cert_chain);
    int certs_in_ocsp = sk_X509_num(OCSP_GET_CERTS(basic_response));

    if (certs_in_chain >= 2 && certs_in_ocsp >= 1) {
        X509 *responder = sk_X509_value(OCSP_GET_CERTS(basic_response), certs_in_ocsp - 1);

        /*check to see if one of the certs in the chain is an issuer of the cert in the ocsp response.*/
        /*if so it needs to be added to the OCSP verification chain.*/
        for (i = 0; i < certs_in_chain; i++) {
            X509 *issuer = sk_X509_value(validator->cert_chain, i);
            int issuer_value = X509_check_issued(issuer, responder);

            if (issuer_value == X509_V_OK) {
                if (!OCSP_basic_add1_cert(basic_response, issuer)) {
                    goto clean_up;
                }
            }
        }
    }

    int ocsp_verify_err = OCSP_basic_verify(basic_response, validator->cert_chain, validator->trust_store->trust_store, 0);
    /* do the crypto checks on the response.*/
    if (!ocsp_verify_err) {
        ret_val = S2N_CERT_ERR_EXPIRED;
        goto clean_up;
    }

    /* for each response check the timestamps and the status. */
    for (i = 0; i < OCSP_resp_count(basic_response); i++) {
        int status_reason;
        ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd;

        OCSP_SINGLERESP *single_response = OCSP_resp_get0(basic_response, i);
        if (!single_response) {
            goto clean_up;
        }

        ocsp_status = OCSP_single_get0_status(single_response, &status_reason, &revtime,
                                              &thisupd, &nextupd);

        uint64_t this_update = 0;
        int thisupd_err = s2n_asn1_time_to_nano_since_epoch_ticks((const char *) thisupd->data,
                                                                  (uint32_t) thisupd->length, &this_update);

        uint64_t next_update = 0;
        int nextupd_err = s2n_asn1_time_to_nano_since_epoch_ticks((const char *) nextupd->data,
                                                                  (uint32_t) nextupd->length, &next_update);

        uint64_t current_time = 0;
        int current_time_err = conn->config->wall_clock(conn->config->sys_clock_ctx, &current_time);

        if (thisupd_err || nextupd_err || current_time_err) {
            ret_val = S2N_CERT_ERR_UNTRUSTED;
            goto clean_up;
        }

        if (current_time < this_update || current_time > next_update) {
            ret_val = S2N_CERT_ERR_EXPIRED;
            goto clean_up;
        }

        switch (ocsp_status) {
            case V_OCSP_CERTSTATUS_GOOD:
                break;

            case V_OCSP_CERTSTATUS_REVOKED:
                ret_val = S2N_CERT_ERR_REVOKED;
                goto clean_up;

            case V_OCSP_CERTSTATUS_UNKNOWN:
                goto clean_up;
            default:
                goto clean_up;
        }
    }

    ret_val = S2N_CERT_OK;

    clean_up:
    if (basic_response) {
        OCSP_BASICRESP_free(basic_response);
    }

    if (ocsp_response) {
        OCSP_RESPONSE_free(ocsp_response);
    }

    return ret_val;
#endif /* S2N_OCSP_STAPLING_SUPPORTED */
}