• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.] */
56 
57 #include <openssl/asn1.h>
58 #include <openssl/digest.h>
59 #include <openssl/err.h>
60 #include <openssl/evp.h>
61 #include <openssl/mem.h>
62 #include <openssl/obj.h>
63 #include <openssl/x509.h>
64 
65 #include "../evp/internal.h"
66 
67 
68 /* TODO(fork): this code appears to be dead. */
69 #if 0
70 #ifndef NO_ASN1_OLD
71 
72 int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
73 	      ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey,
74 	      const EVP_MD *type)
75 	{
76 	EVP_MD_CTX ctx;
77 	unsigned char *p,*buf_in=NULL,*buf_out=NULL;
78 	int i,inl=0,outl=0,outll=0;
79 	X509_ALGOR *a;
80 
81 	EVP_MD_CTX_init(&ctx);
82 	for (i=0; i<2; i++)
83 		{
84 		if (i == 0)
85 			a=algor1;
86 		else
87 			a=algor2;
88 		if (a == NULL) continue;
89                 if (type->pkey_type == NID_dsaWithSHA1)
90 			{
91 			/* special case: RFC 2459 tells us to omit 'parameters'
92 			 * with id-dsa-with-sha1 */
93 			ASN1_TYPE_free(a->parameter);
94 			a->parameter = NULL;
95 			}
96 		else if ((a->parameter == NULL) ||
97 			(a->parameter->type != V_ASN1_NULL))
98 			{
99 			ASN1_TYPE_free(a->parameter);
100 			if ((a->parameter=ASN1_TYPE_new()) == NULL) goto err;
101 			a->parameter->type=V_ASN1_NULL;
102 			}
103 		ASN1_OBJECT_free(a->algorithm);
104 		a->algorithm=OBJ_nid2obj(type->pkey_type);
105 		if (a->algorithm == NULL)
106 			{
107 			OPENSSL_PUT_ERROR(ASN1, XXX, ASN1_R_UNKNOWN_OBJECT_TYPE);
108 			goto err;
109 			}
110 		if (a->algorithm->length == 0)
111 			{
112 			OPENSSL_PUT_ERROR(ASN1, XXX, ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
113 			goto err;
114 			}
115 		}
116 	inl=i2d(data,NULL);
117 	buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl);
118 	outll=outl=EVP_PKEY_size(pkey);
119 	buf_out=(unsigned char *)OPENSSL_malloc((unsigned int)outl);
120 	if ((buf_in == NULL) || (buf_out == NULL))
121 		{
122 		outl=0;
123 		OPENSSL_PUT_ERROR(ASN1, XXX, ERR_R_MALLOC_FAILURE);
124 		goto err;
125 		}
126 	p=buf_in;
127 
128 	i2d(data,&p);
129 	if (!EVP_SignInit_ex(&ctx,type, NULL)
130 		|| !EVP_SignUpdate(&ctx,(unsigned char *)buf_in,inl)
131 		|| !EVP_SignFinal(&ctx,(unsigned char *)buf_out,
132 			(unsigned int *)&outl,pkey))
133 		{
134 		outl=0;
135 		OPENSSL_PUT_ERROR(ASN1, XXX, ERR_R_EVP_LIB);
136 		goto err;
137 		}
138 	if (signature->data != NULL) OPENSSL_free(signature->data);
139 	signature->data=buf_out;
140 	buf_out=NULL;
141 	signature->length=outl;
142 	/* In the interests of compatibility, I'll make sure that
143 	 * the bit string has a 'not-used bits' value of 0
144 	 */
145 	signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
146 	signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
147 err:
148 	EVP_MD_CTX_cleanup(&ctx);
149 	if (buf_in != NULL)
150 		{ OPENSSL_cleanse((char *)buf_in,(unsigned int)inl); OPENSSL_free(buf_in); }
151 	if (buf_out != NULL)
152 		{ OPENSSL_cleanse((char *)buf_out,outll); OPENSSL_free(buf_out); }
153 	return(outl);
154 	}
155 
156 #endif
157 #endif
158 
ASN1_item_sign(const ASN1_ITEM * it,X509_ALGOR * algor1,X509_ALGOR * algor2,ASN1_BIT_STRING * signature,void * asn,EVP_PKEY * pkey,const EVP_MD * type)159 int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
160 	     ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey,
161 	     const EVP_MD *type)
162 	{
163 	EVP_MD_CTX ctx;
164 	EVP_MD_CTX_init(&ctx);
165 	if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey))
166 		{
167 		EVP_MD_CTX_cleanup(&ctx);
168 		return 0;
169 		}
170 	return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx);
171 	}
172 
173 
ASN1_item_sign_ctx(const ASN1_ITEM * it,X509_ALGOR * algor1,X509_ALGOR * algor2,ASN1_BIT_STRING * signature,void * asn,EVP_MD_CTX * ctx)174 int ASN1_item_sign_ctx(const ASN1_ITEM *it,
175 		X509_ALGOR *algor1, X509_ALGOR *algor2,
176 	     	ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
177 	{
178 	const EVP_MD *type;
179 	EVP_PKEY *pkey;
180 	unsigned char *buf_in=NULL,*buf_out=NULL;
181 	size_t inl=0,outl=0,outll=0;
182 	int signid, paramtype;
183 	int rv;
184 
185 	type = EVP_MD_CTX_md(ctx);
186 	pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
187 
188 	if (!type || !pkey)
189 		{
190 		OPENSSL_PUT_ERROR(X509, ASN1_item_sign_ctx, X509_R_CONTEXT_NOT_INITIALISED);
191 		return 0;
192 		}
193 
194 	if (pkey->ameth->item_sign)
195 		{
196 		rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2,
197 						signature);
198 		if (rv == 1)
199 			outl = signature->length;
200 		/* Return value meanings:
201 		 * <=0: error.
202 		 *   1: method does everything.
203 		 *   2: carry on as normal.
204 		 *   3: ASN1 method sets algorithm identifiers: just sign.
205 		 */
206 		if (rv <= 0)
207 			OPENSSL_PUT_ERROR(X509, ASN1_item_sign_ctx, ERR_R_EVP_LIB);
208 		if (rv <= 1)
209 			goto err;
210 		}
211 	else
212 		rv = 2;
213 
214 	if (rv == 2)
215 		{
216 		/* TODO(fork): EVP_MD_FLAG_PKEY_METHOD_SIGNATURE seems to mean
217 		 * "is SHA". */
218 		if (!pkey->ameth ||
219 			!OBJ_find_sigid_by_algs(&signid,
220 						EVP_MD_type(type),
221 						pkey->ameth->pkey_id))
222 			{
223 			OPENSSL_PUT_ERROR(X509, ASN1_item_sign_ctx, X509_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
224 			return 0;
225 			}
226 
227 		if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
228 			paramtype = V_ASN1_NULL;
229 		else
230 			paramtype = V_ASN1_UNDEF;
231 
232 		if (algor1)
233 			X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL);
234 		if (algor2)
235 			X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);
236 
237 		}
238 
239 	inl=ASN1_item_i2d(asn,&buf_in, it);
240 	outll=outl=EVP_PKEY_size(pkey);
241 	buf_out=OPENSSL_malloc((unsigned int)outl);
242 	if ((buf_in == NULL) || (buf_out == NULL))
243 		{
244 		outl=0;
245 		OPENSSL_PUT_ERROR(X509, ASN1_item_sign_ctx, ERR_R_MALLOC_FAILURE);
246 		goto err;
247 		}
248 
249 	if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
250 		|| !EVP_DigestSignFinal(ctx, buf_out, &outl))
251 		{
252 		outl=0;
253 		OPENSSL_PUT_ERROR(X509, ASN1_item_sign_ctx, ERR_R_EVP_LIB);
254 		goto err;
255 		}
256 	if (signature->data != NULL) OPENSSL_free(signature->data);
257 	signature->data=buf_out;
258 	buf_out=NULL;
259 	signature->length=outl;
260 	/* In the interests of compatibility, I'll make sure that
261 	 * the bit string has a 'not-used bits' value of 0
262 	 */
263 	signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
264 	signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
265 err:
266 	EVP_MD_CTX_cleanup(ctx);
267 	if (buf_in != NULL)
268 		{ OPENSSL_cleanse((char *)buf_in,(unsigned int)inl); OPENSSL_free(buf_in); }
269 	if (buf_out != NULL)
270 		{ OPENSSL_cleanse((char *)buf_out,outll); OPENSSL_free(buf_out); }
271 	return(outl);
272 	}
273