155714Skris/* crypto/asn1/a_verify.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
855714Skris *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1555714Skris *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
2255714Skris *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4055714Skris *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
5255714Skris *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include <time.h>
6155714Skris
6255714Skris#include "cryptlib.h"
63238405Sjkim#include "asn1_locl.h"
6459191Skris
6559191Skris#ifndef NO_SYS_TYPES_H
6659191Skris# include <sys/types.h>
6759191Skris#endif
6859191Skris
6955714Skris#include <openssl/bn.h>
7055714Skris#include <openssl/x509.h>
7155714Skris#include <openssl/objects.h>
7255714Skris#include <openssl/buffer.h>
7355714Skris#include <openssl/evp.h>
7455714Skris
75109998Smarkm#ifndef NO_ASN1_OLD
76109998Smarkm
77160814Ssimonint ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
78160814Ssimon		char *data, EVP_PKEY *pkey)
7955714Skris	{
8055714Skris	EVP_MD_CTX ctx;
8155714Skris	const EVP_MD *type;
8255714Skris	unsigned char *p,*buf_in=NULL;
8355714Skris	int ret= -1,i,inl;
8455714Skris
85109998Smarkm	EVP_MD_CTX_init(&ctx);
8655714Skris	i=OBJ_obj2nid(a->algorithm);
8755714Skris	type=EVP_get_digestbyname(OBJ_nid2sn(i));
8855714Skris	if (type == NULL)
8955714Skris		{
9055714Skris		ASN1err(ASN1_F_ASN1_VERIFY,ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
9155714Skris		goto err;
9255714Skris		}
93277195Sdelphij
94277195Sdelphij	if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7)
95277195Sdelphij		{
96277195Sdelphij		ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
97277195Sdelphij		goto err;
98277195Sdelphij		}
9955714Skris
10055714Skris	inl=i2d(data,NULL);
10168651Skris	buf_in=OPENSSL_malloc((unsigned int)inl);
10255714Skris	if (buf_in == NULL)
10355714Skris		{
10455714Skris		ASN1err(ASN1_F_ASN1_VERIFY,ERR_R_MALLOC_FAILURE);
10555714Skris		goto err;
10655714Skris		}
10755714Skris	p=buf_in;
10855714Skris
10955714Skris	i2d(data,&p);
110238405Sjkim	if (!EVP_VerifyInit_ex(&ctx,type, NULL)
111238405Sjkim		|| !EVP_VerifyUpdate(&ctx,(unsigned char *)buf_in,inl))
112194206Ssimon		{
113194206Ssimon		ASN1err(ASN1_F_ASN1_VERIFY,ERR_R_EVP_LIB);
114194206Ssimon		ret=0;
115194206Ssimon		goto err;
116194206Ssimon		}
11755714Skris
118109998Smarkm	OPENSSL_cleanse(buf_in,(unsigned int)inl);
11968651Skris	OPENSSL_free(buf_in);
12055714Skris
12155714Skris	if (EVP_VerifyFinal(&ctx,(unsigned char *)signature->data,
12255714Skris			(unsigned int)signature->length,pkey) <= 0)
12355714Skris		{
12455714Skris		ASN1err(ASN1_F_ASN1_VERIFY,ERR_R_EVP_LIB);
12555714Skris		ret=0;
12655714Skris		goto err;
12755714Skris		}
12855714Skris	/* we don't need to zero the 'ctx' because we just checked
12955714Skris	 * public information */
13055714Skris	/* memset(&ctx,0,sizeof(ctx)); */
13155714Skris	ret=1;
13255714Skriserr:
133109998Smarkm	EVP_MD_CTX_cleanup(&ctx);
13455714Skris	return(ret);
13555714Skris	}
136109998Smarkm
137109998Smarkm#endif
138109998Smarkm
139109998Smarkm
140238405Sjkimint ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
141238405Sjkim		ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
142109998Smarkm	{
143109998Smarkm	EVP_MD_CTX ctx;
144109998Smarkm	unsigned char *buf_in=NULL;
145238405Sjkim	int ret= -1,inl;
146109998Smarkm
147238405Sjkim	int mdnid, pknid;
148238405Sjkim
149246772Sjkim	if (!pkey)
150246772Sjkim		{
151246772Sjkim		ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_PASSED_NULL_PARAMETER);
152246772Sjkim		return -1;
153246772Sjkim		}
154246772Sjkim
155277195Sdelphij	if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7)
156277195Sdelphij		{
157277195Sdelphij		ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
158277195Sdelphij		return -1;
159277195Sdelphij		}
160277195Sdelphij
161109998Smarkm	EVP_MD_CTX_init(&ctx);
162238405Sjkim
163238405Sjkim	/* Convert signature OID into digest and public key OIDs */
164238405Sjkim	if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid))
165109998Smarkm		{
166238405Sjkim		ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
167109998Smarkm		goto err;
168109998Smarkm		}
169238405Sjkim	if (mdnid == NID_undef)
170160814Ssimon		{
171238405Sjkim		if (!pkey->ameth || !pkey->ameth->item_verify)
172238405Sjkim			{
173238405Sjkim			ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
174238405Sjkim			goto err;
175238405Sjkim			}
176238405Sjkim		ret = pkey->ameth->item_verify(&ctx, it, asn, a,
177238405Sjkim							signature, pkey);
178238405Sjkim		/* Return value of 2 means carry on, anything else means we
179238405Sjkim		 * exit straight away: either a fatal error of the underlying
180238405Sjkim		 * verification routine handles all verification.
181238405Sjkim		 */
182238405Sjkim		if (ret != 2)
183238405Sjkim			goto err;
184238405Sjkim		ret = -1;
185160814Ssimon		}
186238405Sjkim	else
187238405Sjkim		{
188238405Sjkim		const EVP_MD *type;
189238405Sjkim		type=EVP_get_digestbynid(mdnid);
190238405Sjkim		if (type == NULL)
191238405Sjkim			{
192238405Sjkim			ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
193238405Sjkim			goto err;
194238405Sjkim			}
195160814Ssimon
196238405Sjkim		/* Check public key OID matches public key type */
197238405Sjkim		if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id)
198238405Sjkim			{
199238405Sjkim			ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_WRONG_PUBLIC_KEY_TYPE);
200238405Sjkim			goto err;
201238405Sjkim			}
202238405Sjkim
203238405Sjkim		if (!EVP_DigestVerifyInit(&ctx, NULL, type, NULL, pkey))
204238405Sjkim			{
205238405Sjkim			ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB);
206238405Sjkim			ret=0;
207238405Sjkim			goto err;
208238405Sjkim			}
209238405Sjkim
210238405Sjkim		}
211238405Sjkim
212109998Smarkm	inl = ASN1_item_i2d(asn, &buf_in, it);
213109998Smarkm
214109998Smarkm	if (buf_in == NULL)
215109998Smarkm		{
216160814Ssimon		ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_MALLOC_FAILURE);
217109998Smarkm		goto err;
218109998Smarkm		}
219109998Smarkm
220238405Sjkim	if (!EVP_DigestVerifyUpdate(&ctx,buf_in,inl))
221238405Sjkim		{
222238405Sjkim		ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB);
223238405Sjkim		ret=0;
224238405Sjkim		goto err;
225238405Sjkim		}
226109998Smarkm
227109998Smarkm	OPENSSL_cleanse(buf_in,(unsigned int)inl);
228109998Smarkm	OPENSSL_free(buf_in);
229109998Smarkm
230238405Sjkim	if (EVP_DigestVerifyFinal(&ctx,signature->data,
231238405Sjkim			(size_t)signature->length) <= 0)
232109998Smarkm		{
233160814Ssimon		ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB);
234109998Smarkm		ret=0;
235109998Smarkm		goto err;
236109998Smarkm		}
237109998Smarkm	/* we don't need to zero the 'ctx' because we just checked
238109998Smarkm	 * public information */
239109998Smarkm	/* memset(&ctx,0,sizeof(ctx)); */
240109998Smarkm	ret=1;
241109998Smarkmerr:
242109998Smarkm	EVP_MD_CTX_cleanup(&ctx);
243109998Smarkm	return(ret);
244109998Smarkm	}
245109998Smarkm
246109998Smarkm
247