/* ocsp_vfy.c */
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
 * project 2000.
 */
/* ====================================================================
 * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
 *
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    licensing@OpenSSL.org.
 *
 * 5. Products derived from this software may not be called "OpenSSL"
 *    nor may "OpenSSL" appear in their names without prior written
 *    permission of the OpenSSL Project.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
 *
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This product includes cryptographic software written by Eric Young
 * (eay@cryptsoft.com).  This product includes software written by Tim
 * Hudson (tjh@cryptsoft.com).
 *
 */

#include <openssl/ocsp.h>
#include <openssl/err.h>
#include <string.h>

static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
				X509_STORE *st, unsigned long flags);
static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id);
static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, unsigned long flags);
static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret);
static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, STACK_OF(OCSP_SINGLERESP) *sresp);
static int ocsp_check_delegated(X509 *x, int flags);
static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm, STACK_OF(X509) *certs,
				X509_STORE *st, unsigned long flags);

/* Verify a basic response message */

int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
				X509_STORE *st, unsigned long flags)
	{
	X509 *signer, *x;
	STACK_OF(X509) *chain = NULL;
	X509_STORE_CTX ctx;
	int i, ret = 0;
	ret = ocsp_find_signer(&signer, bs, certs, st, flags);
	if (!ret)
		{
		OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
		goto end;
		}
	if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
		flags |= OCSP_NOVERIFY;
	if (!(flags & OCSP_NOSIGS))
		{
		EVP_PKEY *skey;
		skey = X509_get_pubkey(signer);
		ret = OCSP_BASICRESP_verify(bs, skey, 0);
		EVP_PKEY_free(skey);
		if(ret <= 0)
			{
			OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNATURE_FAILURE);
			goto end;
			}
		}
	if (!(flags & OCSP_NOVERIFY))
		{
		int init_res;
		if(flags & OCSP_NOCHAIN)
			init_res = X509_STORE_CTX_init(&ctx, st, signer, NULL);
		else
			init_res = X509_STORE_CTX_init(&ctx, st, signer, bs->certs);
		if(!init_res)
			{
			OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,ERR_R_X509_LIB);
			goto end;
			}

		X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER);
		ret = X509_verify_cert(&ctx);
		chain = X509_STORE_CTX_get1_chain(&ctx);
		X509_STORE_CTX_cleanup(&ctx);
                if (ret <= 0)
			{
			i = X509_STORE_CTX_get_error(&ctx);	
			OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,OCSP_R_CERTIFICATE_VERIFY_ERROR);
			ERR_add_error_data(2, "Verify error:",
					X509_verify_cert_error_string(i));
                        goto end;
                	}
		if(flags & OCSP_NOCHECKS)
			{
			ret = 1;
			goto end;
			}
		/* At this point we have a valid certificate chain
		 * need to verify it against the OCSP issuer criteria.
		 */
		ret = ocsp_check_issuer(bs, chain, flags);

		/* If fatal error or valid match then finish */
		if (ret != 0) goto end;

		/* Easy case: explicitly trusted. Get root CA and
		 * check for explicit trust
		 */
		if(flags & OCSP_NOEXPLICIT) goto end;

		x = sk_X509_value(chain, sk_X509_num(chain) - 1);
		if(X509_check_trust(x, NID_OCSP_sign, 0) != X509_TRUST_TRUSTED)
			{
			OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,OCSP_R_ROOT_CA_NOT_TRUSTED);
			goto end;
			}
		ret = 1;
		}



	end:
	if(chain) sk_X509_pop_free(chain, X509_free);
	return ret;
	}


static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
				X509_STORE *st, unsigned long flags)
	{
	X509 *signer;
	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
	if ((signer = ocsp_find_signer_sk(certs, rid)))
		{
		*psigner = signer;
		return 2;
		}
	if(!(flags & OCSP_NOINTERN) &&
	    (signer = ocsp_find_signer_sk(bs->certs, rid)))
		{
		*psigner = signer;
		return 1;
		}
	/* Maybe lookup from store if by subject name */

	*psigner = NULL;
	return 0;
	}


static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
	{
	int i;
	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
	X509 *x;

	/* Easy if lookup by name */
	if (id->type == V_OCSP_RESPID_NAME)
		return X509_find_by_subject(certs, id->value.byName);

	/* Lookup by key hash */

	/* If key hash isn't SHA1 length then forget it */
	if (id->value.byKey->length != SHA_DIGEST_LENGTH) return NULL;
	keyhash = id->value.byKey->data;
	/* Calculate hash of each key and compare */
	for (i = 0; i < sk_X509_num(certs); i++)
		{
		x = sk_X509_value(certs, i);
		X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
		if(!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
			return x;
		}
	return NULL;
	}


static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, unsigned long flags)
	{
	STACK_OF(OCSP_SINGLERESP) *sresp;
	X509 *signer, *sca;
	OCSP_CERTID *caid = NULL;
	int i;
	sresp = bs->tbsResponseData->responses;

	if (sk_X509_num(chain) <= 0)
		{
		OCSPerr(OCSP_F_OCSP_CHECK_ISSUER, OCSP_R_NO_CERTIFICATES_IN_CHAIN);
		return -1;
		}

	/* See if the issuer IDs match. */
	i = ocsp_check_ids(sresp, &caid);

	/* If ID mismatch or other error then return */
	if (i <= 0) return i;

	signer = sk_X509_value(chain, 0);
	/* Check to see if OCSP responder CA matches request CA */
	if (sk_X509_num(chain) > 1)
		{
		sca = sk_X509_value(chain, 1);
		i = ocsp_match_issuerid(sca, caid, sresp);
		if (i < 0) return i;
		if (i)
			{
			/* We have a match, if extensions OK then success */
			if (ocsp_check_delegated(signer, flags)) return 1;
			return 0;
			}
		}

	/* Otherwise check if OCSP request signed directly by request CA */
	return ocsp_match_issuerid(signer, caid, sresp);
	}


/* Check the issuer certificate IDs for equality. If there is a mismatch with the same
 * algorithm then there's no point trying to match any certificates against the issuer.
 * If the issuer IDs all match then we just need to check equality against one of them.
 */
	
static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret)
	{
	OCSP_CERTID *tmpid, *cid;
	int i, idcount;

	idcount = sk_OCSP_SINGLERESP_num(sresp);
	if (idcount <= 0)
		{
		OCSPerr(OCSP_F_OCSP_CHECK_IDS, OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA);
		return -1;
		}

	cid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId;

	*ret = NULL;

	for (i = 1; i < idcount; i++)
		{
		tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId;
		/* Check to see if IDs match */
		if (OCSP_id_issuer_cmp(cid, tmpid))
			{
			/* If algoritm mismatch let caller deal with it */
			if (OBJ_cmp(tmpid->hashAlgorithm->algorithm,
					cid->hashAlgorithm->algorithm))
					return 2;
			/* Else mismatch */
			return 0;
			}
		}

	/* All IDs match: only need to check one ID */
	*ret = cid;
	return 1;
	}


static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid,
			STACK_OF(OCSP_SINGLERESP) *sresp)
	{
	/* If only one ID to match then do it */
	if(cid)
		{
		const EVP_MD *dgst;
		X509_NAME *iname;
		int mdlen;
		unsigned char md[EVP_MAX_MD_SIZE];
		if (!(dgst = EVP_get_digestbyobj(cid->hashAlgorithm->algorithm)))
			{
			OCSPerr(OCSP_F_OCSP_MATCH_ISSUERID, OCSP_R_UNKNOWN_MESSAGE_DIGEST);
			return -1;
			}

		mdlen = EVP_MD_size(dgst);
		if ((cid->issuerNameHash->length != mdlen) ||
		   (cid->issuerKeyHash->length != mdlen))
			return 0;
		iname = X509_get_subject_name(cert);
		if (!X509_NAME_digest(iname, dgst, md, NULL))
			return -1;
		if (memcmp(md, cid->issuerNameHash->data, mdlen))
			return 0;
		X509_pubkey_digest(cert, EVP_sha1(), md, NULL);
		if (memcmp(md, cid->issuerKeyHash->data, mdlen))
			return 0;

		return 1;

		}
	else
		{
		/* We have to match the whole lot */
		int i, ret;
		OCSP_CERTID *tmpid;
		for (i = 0; i < sk_OCSP_SINGLERESP_num(sresp); i++)
			{
			tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId;
			ret = ocsp_match_issuerid(cert, tmpid, NULL);
			if (ret <= 0) return ret;
			}
		return 1;
		}
			
	}

static int ocsp_check_delegated(X509 *x, int flags)
	{
	X509_check_purpose(x, -1, 0);
	if ((x->ex_flags & EXFLAG_XKUSAGE) &&
	    (x->ex_xkusage & XKU_OCSP_SIGN))
		return 1;
	OCSPerr(OCSP_F_OCSP_CHECK_DELEGATED, OCSP_R_MISSING_OCSPSIGNING_USAGE);
	return 0;
	}

/* Verify an OCSP request. This is fortunately much easier than OCSP
 * response verify. Just find the signers certificate and verify it
 * against a given trust value.
 */

int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, unsigned long flags)
        {
	X509 *signer;
	X509_NAME *nm;
	GENERAL_NAME *gen;
	int ret;
	X509_STORE_CTX ctx;
	if (!req->optionalSignature) 
		{
		OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_REQUEST_NOT_SIGNED);
		return 0;
		}
	gen = req->tbsRequest->requestorName;
	if (gen->type != GEN_DIRNAME)
		{
		OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE);
		return 0;
		}
	nm = gen->d.directoryName;
	ret = ocsp_req_find_signer(&signer, req, nm, certs, store, flags);
	if (ret <= 0)
		{
		OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
		return 0;
		}
	if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
		flags |= OCSP_NOVERIFY;
	if (!(flags & OCSP_NOSIGS))
		{
		EVP_PKEY *skey;
		skey = X509_get_pubkey(signer);
		ret = OCSP_REQUEST_verify(req, skey);
		EVP_PKEY_free(skey);
		if(ret <= 0)
			{
			OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNATURE_FAILURE);
			return 0;
			}
		}
	if (!(flags & OCSP_NOVERIFY))
		{
		int init_res;
		if(flags & OCSP_NOCHAIN)
			init_res = X509_STORE_CTX_init(&ctx, store, signer, NULL);
		else
			init_res = X509_STORE_CTX_init(&ctx, store, signer,
					req->optionalSignature->certs);
		if(!init_res)
			{
			OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,ERR_R_X509_LIB);
			return 0;
			}

		X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER);
		X509_STORE_CTX_set_trust(&ctx, X509_TRUST_OCSP_REQUEST);
		ret = X509_verify_cert(&ctx);
		X509_STORE_CTX_cleanup(&ctx);
                if (ret <= 0)
			{
			ret = X509_STORE_CTX_get_error(&ctx);	
			OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,OCSP_R_CERTIFICATE_VERIFY_ERROR);
			ERR_add_error_data(2, "Verify error:",
					X509_verify_cert_error_string(ret));
                        return 0;
                	}
		}
	return 1;
        }

static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm, STACK_OF(X509) *certs,
				X509_STORE *st, unsigned long flags)
	{
	X509 *signer;
	if(!(flags & OCSP_NOINTERN))
		{
		signer = X509_find_by_subject(req->optionalSignature->certs, nm);
		*psigner = signer;
		return 1;
		}

	signer = X509_find_by_subject(certs, nm);
	if (signer)
		{
		*psigner = signer;
		return 2;
		}
	return 0;
	}
