1 /* $OpenBSD: pmeth_fn.c,v 1.4 2014/07/11 08:44:48 jsing Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project 2006.
4  */
5 /* ====================================================================
6  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58 
59 #include <stdio.h>
60 #include <stdlib.h>
61 
62 #include <openssl/err.h>
63 #include <openssl/evp.h>
64 #include <openssl/objects.h>
65 
66 #include "evp_locl.h"
67 
68 #define M_check_autoarg(ctx, arg, arglen, err) \
69 	if (ctx->pmeth->flags & EVP_PKEY_FLAG_AUTOARGLEN) \
70 		{ \
71 		size_t pksize = (size_t)EVP_PKEY_size(ctx->pkey); \
72 		if (!arg) \
73 			{ \
74 			*arglen = pksize; \
75 			return 1; \
76 			} \
77 		else if (*arglen < pksize) \
78 			{ \
79 			EVPerr(err, EVP_R_BUFFER_TOO_SMALL); /*ckerr_ignore*/\
80 			return 0; \
81 			} \
82 		}
83 
84 int
85 EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx)
86 {
87 	int ret;
88 
89 	if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) {
90 		EVPerr(EVP_F_EVP_PKEY_SIGN_INIT,
91 		    EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
92 		return -2;
93 	}
94 	ctx->operation = EVP_PKEY_OP_SIGN;
95 	if (!ctx->pmeth->sign_init)
96 		return 1;
97 	ret = ctx->pmeth->sign_init(ctx);
98 	if (ret <= 0)
99 		ctx->operation = EVP_PKEY_OP_UNDEFINED;
100 	return ret;
101 }
102 
103 int
104 EVP_PKEY_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
105     const unsigned char *tbs, size_t tbslen)
106 {
107 	if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) {
108 		EVPerr(EVP_F_EVP_PKEY_SIGN,
109 		    EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
110 		return -2;
111 	}
112 	if (ctx->operation != EVP_PKEY_OP_SIGN) {
113 		EVPerr(EVP_F_EVP_PKEY_SIGN, EVP_R_OPERATON_NOT_INITIALIZED);
114 		return -1;
115 	}
116 	M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN)
117 	return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen);
118 }
119 
120 int
121 EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx)
122 {
123 	int ret;
124 
125 	if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) {
126 		EVPerr(EVP_F_EVP_PKEY_VERIFY_INIT,
127 		    EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
128 		return -2;
129 	}
130 	ctx->operation = EVP_PKEY_OP_VERIFY;
131 	if (!ctx->pmeth->verify_init)
132 		return 1;
133 	ret = ctx->pmeth->verify_init(ctx);
134 	if (ret <= 0)
135 		ctx->operation = EVP_PKEY_OP_UNDEFINED;
136 	return ret;
137 }
138 
139 int
140 EVP_PKEY_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen,
141     const unsigned char *tbs, size_t tbslen)
142 {
143 	if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) {
144 		EVPerr(EVP_F_EVP_PKEY_VERIFY,
145 		    EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
146 		return -2;
147 	}
148 	if (ctx->operation != EVP_PKEY_OP_VERIFY) {
149 		EVPerr(EVP_F_EVP_PKEY_VERIFY, EVP_R_OPERATON_NOT_INITIALIZED);
150 		return -1;
151 	}
152 	return ctx->pmeth->verify(ctx, sig, siglen, tbs, tbslen);
153 }
154 
155 int
156 EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx)
157 {
158 	int ret;
159 
160 	if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) {
161 		EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT,
162 		    EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
163 		return -2;
164 	}
165 	ctx->operation = EVP_PKEY_OP_VERIFYRECOVER;
166 	if (!ctx->pmeth->verify_recover_init)
167 		return 1;
168 	ret = ctx->pmeth->verify_recover_init(ctx);
169 	if (ret <= 0)
170 		ctx->operation = EVP_PKEY_OP_UNDEFINED;
171 	return ret;
172 }
173 
174 int
175 EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, unsigned char *rout, size_t *routlen,
176     const unsigned char *sig, size_t siglen)
177 {
178 	if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) {
179 		EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER,
180 		    EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
181 		return -2;
182 	}
183 	if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) {
184 		EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER,
185 		    EVP_R_OPERATON_NOT_INITIALIZED);
186 		return -1;
187 	}
188 	M_check_autoarg(ctx, rout, routlen, EVP_F_EVP_PKEY_VERIFY_RECOVER)
189 	return ctx->pmeth->verify_recover(ctx, rout, routlen, sig, siglen);
190 }
191 
192 int
193 EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx)
194 {
195 	int ret;
196 
197 	if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) {
198 		EVPerr(EVP_F_EVP_PKEY_ENCRYPT_INIT,
199 		    EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
200 		return -2;
201 	}
202 	ctx->operation = EVP_PKEY_OP_ENCRYPT;
203 	if (!ctx->pmeth->encrypt_init)
204 		return 1;
205 	ret = ctx->pmeth->encrypt_init(ctx);
206 	if (ret <= 0)
207 		ctx->operation = EVP_PKEY_OP_UNDEFINED;
208 	return ret;
209 }
210 
211 int
212 EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
213     const unsigned char *in, size_t inlen)
214 {
215 	if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) {
216 		EVPerr(EVP_F_EVP_PKEY_ENCRYPT,
217 		    EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
218 		return -2;
219 	}
220 	if (ctx->operation != EVP_PKEY_OP_ENCRYPT) {
221 		EVPerr(EVP_F_EVP_PKEY_ENCRYPT, EVP_R_OPERATON_NOT_INITIALIZED);
222 		return -1;
223 	}
224 	M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_ENCRYPT)
225 	return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen);
226 }
227 
228 int
229 EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx)
230 {
231 	int ret;
232 
233 	if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) {
234 		EVPerr(EVP_F_EVP_PKEY_DECRYPT_INIT,
235 		    EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
236 		return -2;
237 	}
238 	ctx->operation = EVP_PKEY_OP_DECRYPT;
239 	if (!ctx->pmeth->decrypt_init)
240 		return 1;
241 	ret = ctx->pmeth->decrypt_init(ctx);
242 	if (ret <= 0)
243 		ctx->operation = EVP_PKEY_OP_UNDEFINED;
244 	return ret;
245 }
246 
247 int
248 EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
249     const unsigned char *in, size_t inlen)
250 {
251 	if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) {
252 		EVPerr(EVP_F_EVP_PKEY_DECRYPT,
253 		    EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
254 		return -2;
255 	}
256 	if (ctx->operation != EVP_PKEY_OP_DECRYPT) {
257 		EVPerr(EVP_F_EVP_PKEY_DECRYPT, EVP_R_OPERATON_NOT_INITIALIZED);
258 		return -1;
259 	}
260 	M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_DECRYPT)
261 	return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen);
262 }
263 
264 int
265 EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
266 {
267 	int ret;
268 
269 	if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) {
270 		EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT,
271 		    EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
272 		return -2;
273 	}
274 	ctx->operation = EVP_PKEY_OP_DERIVE;
275 	if (!ctx->pmeth->derive_init)
276 		return 1;
277 	ret = ctx->pmeth->derive_init(ctx);
278 	if (ret <= 0)
279 		ctx->operation = EVP_PKEY_OP_UNDEFINED;
280 	return ret;
281 }
282 
283 int
284 EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
285 {
286 	int ret;
287 
288 	if (!ctx || !ctx->pmeth || !(ctx->pmeth->derive ||
289 	    ctx->pmeth->encrypt || ctx->pmeth->decrypt) ||
290 	    !ctx->pmeth->ctrl) {
291 		EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
292 		    EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
293 		return -2;
294 	}
295 	if (ctx->operation != EVP_PKEY_OP_DERIVE &&
296 	    ctx->operation != EVP_PKEY_OP_ENCRYPT &&
297 	    ctx->operation != EVP_PKEY_OP_DECRYPT) {
298 		EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
299 		    EVP_R_OPERATON_NOT_INITIALIZED);
300 		return -1;
301 	}
302 
303 	ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer);
304 
305 	if (ret <= 0)
306 		return ret;
307 
308 	if (ret == 2)
309 		return 1;
310 
311 	if (!ctx->pkey) {
312 		EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_NO_KEY_SET);
313 		return -1;
314 	}
315 
316 	if (ctx->pkey->type != peer->type) {
317 		EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
318 		    EVP_R_DIFFERENT_KEY_TYPES);
319 		return -1;
320 	}
321 
322 	/* ran@cryptocom.ru: For clarity.  The error is if parameters in peer are
323 	 * present (!missing) but don't match.  EVP_PKEY_cmp_parameters may return
324 	 * 1 (match), 0 (don't match) and -2 (comparison is not defined).  -1
325 	 * (different key types) is impossible here because it is checked earlier.
326 	 * -2 is OK for us here, as well as 1, so we can check for 0 only. */
327 	if (!EVP_PKEY_missing_parameters(peer) &&
328 	    !EVP_PKEY_cmp_parameters(ctx->pkey, peer)) {
329 		EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
330 		    EVP_R_DIFFERENT_PARAMETERS);
331 		return -1;
332 	}
333 
334 	EVP_PKEY_free(ctx->peerkey);
335 	ctx->peerkey = peer;
336 
337 	ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer);
338 
339 	if (ret <= 0) {
340 		ctx->peerkey = NULL;
341 		return ret;
342 	}
343 
344 	CRYPTO_add(&peer->references, 1, CRYPTO_LOCK_EVP_PKEY);
345 	return 1;
346 }
347 
348 int
349 EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen)
350 {
351 	if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) {
352 		EVPerr(EVP_F_EVP_PKEY_DERIVE,
353 		    EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
354 		return -2;
355 	}
356 	if (ctx->operation != EVP_PKEY_OP_DERIVE) {
357 		EVPerr(EVP_F_EVP_PKEY_DERIVE, EVP_R_OPERATON_NOT_INITIALIZED);
358 		return -1;
359 	}
360 	M_check_autoarg(ctx, key, pkeylen, EVP_F_EVP_PKEY_DERIVE)
361 	return ctx->pmeth->derive(ctx, key, pkeylen);
362 }
363