1238384Sjkim/* m_sigver.c */
2238384Sjkim/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3238384Sjkim * project 2006.
4238384Sjkim */
5238384Sjkim/* ====================================================================
6238384Sjkim * Copyright (c) 2006,2007 The OpenSSL Project.  All rights reserved.
7238384Sjkim *
8238384Sjkim * Redistribution and use in source and binary forms, with or without
9238384Sjkim * modification, are permitted provided that the following conditions
10238384Sjkim * are met:
11238384Sjkim *
12238384Sjkim * 1. Redistributions of source code must retain the above copyright
13238384Sjkim *    notice, this list of conditions and the following disclaimer.
14238384Sjkim *
15238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright
16238384Sjkim *    notice, this list of conditions and the following disclaimer in
17238384Sjkim *    the documentation and/or other materials provided with the
18238384Sjkim *    distribution.
19238384Sjkim *
20238384Sjkim * 3. All advertising materials mentioning features or use of this
21238384Sjkim *    software must display the following acknowledgment:
22238384Sjkim *    "This product includes software developed by the OpenSSL Project
23238384Sjkim *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24238384Sjkim *
25238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26238384Sjkim *    endorse or promote products derived from this software without
27238384Sjkim *    prior written permission. For written permission, please contact
28238384Sjkim *    licensing@OpenSSL.org.
29238384Sjkim *
30238384Sjkim * 5. Products derived from this software may not be called "OpenSSL"
31238384Sjkim *    nor may "OpenSSL" appear in their names without prior written
32238384Sjkim *    permission of the OpenSSL Project.
33238384Sjkim *
34238384Sjkim * 6. Redistributions of any form whatsoever must retain the following
35238384Sjkim *    acknowledgment:
36238384Sjkim *    "This product includes software developed by the OpenSSL Project
37238384Sjkim *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38238384Sjkim *
39238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42238384Sjkim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE.
51238384Sjkim * ====================================================================
52238384Sjkim *
53238384Sjkim * This product includes cryptographic software written by Eric Young
54238384Sjkim * (eay@cryptsoft.com).  This product includes software written by Tim
55238384Sjkim * Hudson (tjh@cryptsoft.com).
56238384Sjkim *
57238384Sjkim */
58238384Sjkim
59238384Sjkim#include <stdio.h>
60238384Sjkim#include "cryptlib.h"
61238384Sjkim#include <openssl/evp.h>
62238384Sjkim#include <openssl/objects.h>
63238384Sjkim#include <openssl/x509.h>
64238384Sjkim#include "evp_locl.h"
65238384Sjkim
66238384Sjkimstatic int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
67238384Sjkim			  const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey,
68238384Sjkim			  int ver)
69238384Sjkim	{
70238384Sjkim	if (ctx->pctx == NULL)
71238384Sjkim		ctx->pctx = EVP_PKEY_CTX_new(pkey, e);
72238384Sjkim	if (ctx->pctx == NULL)
73238384Sjkim		return 0;
74238384Sjkim
75238384Sjkim	if (type == NULL)
76238384Sjkim		{
77238384Sjkim		int def_nid;
78238384Sjkim		if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0)
79238384Sjkim			type = EVP_get_digestbynid(def_nid);
80238384Sjkim		}
81238384Sjkim
82238384Sjkim	if (type == NULL)
83238384Sjkim		{
84238384Sjkim		EVPerr(EVP_F_DO_SIGVER_INIT, EVP_R_NO_DEFAULT_DIGEST);
85238384Sjkim		return 0;
86238384Sjkim		}
87238384Sjkim
88238384Sjkim	if (ver)
89238384Sjkim		{
90238384Sjkim		if (ctx->pctx->pmeth->verifyctx_init)
91238384Sjkim			{
92238384Sjkim			if (ctx->pctx->pmeth->verifyctx_init(ctx->pctx, ctx) <=0)
93238384Sjkim				return 0;
94238384Sjkim			ctx->pctx->operation = EVP_PKEY_OP_VERIFYCTX;
95238384Sjkim			}
96238384Sjkim		else if (EVP_PKEY_verify_init(ctx->pctx) <= 0)
97238384Sjkim			return 0;
98238384Sjkim		}
99238384Sjkim	else
100238384Sjkim		{
101238384Sjkim		if (ctx->pctx->pmeth->signctx_init)
102238384Sjkim			{
103238384Sjkim			if (ctx->pctx->pmeth->signctx_init(ctx->pctx, ctx) <= 0)
104238384Sjkim				return 0;
105238384Sjkim			ctx->pctx->operation = EVP_PKEY_OP_SIGNCTX;
106238384Sjkim			}
107238384Sjkim		else if (EVP_PKEY_sign_init(ctx->pctx) <= 0)
108238384Sjkim			return 0;
109238384Sjkim		}
110238384Sjkim	if (EVP_PKEY_CTX_set_signature_md(ctx->pctx, type) <= 0)
111238384Sjkim		return 0;
112238384Sjkim	if (pctx)
113238384Sjkim		*pctx = ctx->pctx;
114238384Sjkim	if (!EVP_DigestInit_ex(ctx, type, e))
115238384Sjkim		return 0;
116238384Sjkim	return 1;
117238384Sjkim	}
118238384Sjkim
119238384Sjkimint EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
120238384Sjkim			const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey)
121238384Sjkim	{
122238384Sjkim	return do_sigver_init(ctx, pctx, type, e, pkey, 0);
123238384Sjkim	}
124238384Sjkim
125238384Sjkimint EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
126238384Sjkim			const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey)
127238384Sjkim	{
128238384Sjkim	return do_sigver_init(ctx, pctx, type, e, pkey, 1);
129238384Sjkim	}
130238384Sjkim
131238384Sjkimint EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen)
132238384Sjkim	{
133238384Sjkim	int sctx, r = 0;
134238384Sjkim	if (ctx->pctx->pmeth->signctx)
135238384Sjkim		sctx = 1;
136238384Sjkim	else
137238384Sjkim		sctx = 0;
138238384Sjkim	if (sigret)
139238384Sjkim		{
140238384Sjkim		EVP_MD_CTX tmp_ctx;
141238384Sjkim		unsigned char md[EVP_MAX_MD_SIZE];
142238384Sjkim		unsigned int mdlen;
143238384Sjkim		EVP_MD_CTX_init(&tmp_ctx);
144238384Sjkim		if (!EVP_MD_CTX_copy_ex(&tmp_ctx,ctx))
145238384Sjkim		     	return 0;
146238384Sjkim		if (sctx)
147238384Sjkim			r = tmp_ctx.pctx->pmeth->signctx(tmp_ctx.pctx,
148238384Sjkim					sigret, siglen, &tmp_ctx);
149238384Sjkim		else
150238384Sjkim			r = EVP_DigestFinal_ex(&tmp_ctx,md,&mdlen);
151238384Sjkim		EVP_MD_CTX_cleanup(&tmp_ctx);
152238384Sjkim		if (sctx || !r)
153238384Sjkim			return r;
154238384Sjkim		if (EVP_PKEY_sign(ctx->pctx, sigret, siglen, md, mdlen) <= 0)
155238384Sjkim			return 0;
156238384Sjkim		}
157238384Sjkim	else
158238384Sjkim		{
159238384Sjkim		if (sctx)
160238384Sjkim			{
161238384Sjkim			if (ctx->pctx->pmeth->signctx(ctx->pctx, sigret, siglen, ctx) <= 0)
162238384Sjkim				return 0;
163238384Sjkim			}
164238384Sjkim		else
165238384Sjkim			{
166238384Sjkim			int s = EVP_MD_size(ctx->digest);
167238384Sjkim			if (s < 0 || EVP_PKEY_sign(ctx->pctx, sigret, siglen, NULL, s) <= 0)
168238384Sjkim				return 0;
169238384Sjkim			}
170238384Sjkim		}
171238384Sjkim	return 1;
172238384Sjkim	}
173238384Sjkim
174238384Sjkimint EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, unsigned char *sig, size_t siglen)
175238384Sjkim	{
176238384Sjkim	EVP_MD_CTX tmp_ctx;
177238384Sjkim	unsigned char md[EVP_MAX_MD_SIZE];
178238384Sjkim	int r;
179238384Sjkim	unsigned int mdlen;
180238384Sjkim	int vctx;
181238384Sjkim
182238384Sjkim	if (ctx->pctx->pmeth->verifyctx)
183238384Sjkim		vctx = 1;
184238384Sjkim	else
185238384Sjkim		vctx = 0;
186238384Sjkim	EVP_MD_CTX_init(&tmp_ctx);
187238384Sjkim	if (!EVP_MD_CTX_copy_ex(&tmp_ctx,ctx))
188238384Sjkim		return -1;
189238384Sjkim	if (vctx)
190238384Sjkim		{
191238384Sjkim		r = tmp_ctx.pctx->pmeth->verifyctx(tmp_ctx.pctx,
192238384Sjkim					sig, siglen, &tmp_ctx);
193238384Sjkim		}
194238384Sjkim	else
195238384Sjkim		r = EVP_DigestFinal_ex(&tmp_ctx,md,&mdlen);
196238384Sjkim	EVP_MD_CTX_cleanup(&tmp_ctx);
197238384Sjkim	if (vctx || !r)
198238384Sjkim		return r;
199238384Sjkim	return EVP_PKEY_verify(ctx->pctx, sig, siglen, md, mdlen);
200238384Sjkim	}
201