1 /* Copyright (C) 1995-1998 Eric Young ([email protected])
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young ([email protected]).
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 ([email protected]).
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 ([email protected])"
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 ([email protected])"
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/evp.h>
58
59 #include <assert.h>
60 #include <string.h>
61
62 #include <openssl/err.h>
63 #include <openssl/mem.h>
64 #include <openssl/nid.h>
65 #include <openssl/thread.h>
66
67 #include "internal.h"
68 #include "../internal.h"
69
70
71 // Node depends on |EVP_R_NOT_XOF_OR_INVALID_LENGTH|.
72 //
73 // TODO(davidben): Fix Node to not touch the error queue itself and remove this.
OPENSSL_DECLARE_ERROR_REASON(EVP,NOT_XOF_OR_INVALID_LENGTH)74 OPENSSL_DECLARE_ERROR_REASON(EVP, NOT_XOF_OR_INVALID_LENGTH)
75
76 // The HPKE module uses the EVP error namespace, but it lives in another
77 // directory.
78 OPENSSL_DECLARE_ERROR_REASON(EVP, EMPTY_PSK)
79
80 EVP_PKEY *EVP_PKEY_new(void) {
81 EVP_PKEY *ret = OPENSSL_zalloc(sizeof(EVP_PKEY));
82 if (ret == NULL) {
83 return NULL;
84 }
85
86 ret->type = EVP_PKEY_NONE;
87 ret->references = 1;
88 return ret;
89 }
90
free_it(EVP_PKEY * pkey)91 static void free_it(EVP_PKEY *pkey) {
92 if (pkey->ameth && pkey->ameth->pkey_free) {
93 pkey->ameth->pkey_free(pkey);
94 pkey->pkey = NULL;
95 pkey->type = EVP_PKEY_NONE;
96 }
97 }
98
EVP_PKEY_free(EVP_PKEY * pkey)99 void EVP_PKEY_free(EVP_PKEY *pkey) {
100 if (pkey == NULL) {
101 return;
102 }
103
104 if (!CRYPTO_refcount_dec_and_test_zero(&pkey->references)) {
105 return;
106 }
107
108 free_it(pkey);
109 OPENSSL_free(pkey);
110 }
111
EVP_PKEY_up_ref(EVP_PKEY * pkey)112 int EVP_PKEY_up_ref(EVP_PKEY *pkey) {
113 CRYPTO_refcount_inc(&pkey->references);
114 return 1;
115 }
116
EVP_PKEY_is_opaque(const EVP_PKEY * pkey)117 int EVP_PKEY_is_opaque(const EVP_PKEY *pkey) {
118 if (pkey->ameth && pkey->ameth->pkey_opaque) {
119 return pkey->ameth->pkey_opaque(pkey);
120 }
121 return 0;
122 }
123
EVP_PKEY_cmp(const EVP_PKEY * a,const EVP_PKEY * b)124 int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
125 if (a->type != b->type) {
126 return -1;
127 }
128
129 if (a->ameth) {
130 int ret;
131 // Compare parameters if the algorithm has them
132 if (a->ameth->param_cmp) {
133 ret = a->ameth->param_cmp(a, b);
134 if (ret <= 0) {
135 return ret;
136 }
137 }
138
139 if (a->ameth->pub_cmp) {
140 return a->ameth->pub_cmp(a, b);
141 }
142 }
143
144 return -2;
145 }
146
EVP_PKEY_copy_parameters(EVP_PKEY * to,const EVP_PKEY * from)147 int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
148 if (to->type == EVP_PKEY_NONE) {
149 evp_pkey_set_method(to, from->ameth);
150 } else if (to->type != from->type) {
151 OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES);
152 return 0;
153 }
154
155 if (EVP_PKEY_missing_parameters(from)) {
156 OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
157 return 0;
158 }
159
160 // Once set, parameters may not change.
161 if (!EVP_PKEY_missing_parameters(to)) {
162 if (EVP_PKEY_cmp_parameters(to, from) == 1) {
163 return 1;
164 }
165 OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_PARAMETERS);
166 return 0;
167 }
168
169 if (from->ameth && from->ameth->param_copy) {
170 return from->ameth->param_copy(to, from);
171 }
172
173 // TODO(https://crbug.com/boringssl/536): If the algorithm takes no
174 // parameters, copying them should vacuously succeed.
175 return 0;
176 }
177
EVP_PKEY_missing_parameters(const EVP_PKEY * pkey)178 int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey) {
179 if (pkey->ameth && pkey->ameth->param_missing) {
180 return pkey->ameth->param_missing(pkey);
181 }
182 return 0;
183 }
184
EVP_PKEY_size(const EVP_PKEY * pkey)185 int EVP_PKEY_size(const EVP_PKEY *pkey) {
186 if (pkey && pkey->ameth && pkey->ameth->pkey_size) {
187 return pkey->ameth->pkey_size(pkey);
188 }
189 return 0;
190 }
191
EVP_PKEY_bits(const EVP_PKEY * pkey)192 int EVP_PKEY_bits(const EVP_PKEY *pkey) {
193 if (pkey && pkey->ameth && pkey->ameth->pkey_bits) {
194 return pkey->ameth->pkey_bits(pkey);
195 }
196 return 0;
197 }
198
EVP_PKEY_id(const EVP_PKEY * pkey)199 int EVP_PKEY_id(const EVP_PKEY *pkey) {
200 return pkey->type;
201 }
202
203 // evp_pkey_asn1_find returns the ASN.1 method table for the given |nid|, which
204 // should be one of the |EVP_PKEY_*| values. It returns NULL if |nid| is
205 // unknown.
evp_pkey_asn1_find(int nid)206 static const EVP_PKEY_ASN1_METHOD *evp_pkey_asn1_find(int nid) {
207 switch (nid) {
208 case EVP_PKEY_RSA:
209 return &rsa_asn1_meth;
210 case EVP_PKEY_EC:
211 return &ec_asn1_meth;
212 case EVP_PKEY_DSA:
213 return &dsa_asn1_meth;
214 case EVP_PKEY_ED25519:
215 return &ed25519_asn1_meth;
216 case EVP_PKEY_X25519:
217 return &x25519_asn1_meth;
218 default:
219 return NULL;
220 }
221 }
222
evp_pkey_set_method(EVP_PKEY * pkey,const EVP_PKEY_ASN1_METHOD * method)223 void evp_pkey_set_method(EVP_PKEY *pkey, const EVP_PKEY_ASN1_METHOD *method) {
224 free_it(pkey);
225 pkey->ameth = method;
226 pkey->type = pkey->ameth->pkey_id;
227 }
228
EVP_PKEY_type(int nid)229 int EVP_PKEY_type(int nid) {
230 // In OpenSSL, this was used to map between type aliases. BoringSSL supports
231 // no type aliases, so this function is just the identity.
232 return nid;
233 }
234
EVP_PKEY_assign(EVP_PKEY * pkey,int type,void * key)235 int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) {
236 // This function can only be used to assign RSA, DSA, EC, and DH keys. Other
237 // key types have internal representations which are not exposed through the
238 // public API.
239 switch (type) {
240 case EVP_PKEY_RSA:
241 return EVP_PKEY_assign_RSA(pkey, key);
242 case EVP_PKEY_DSA:
243 return EVP_PKEY_assign_DSA(pkey, key);
244 case EVP_PKEY_EC:
245 return EVP_PKEY_assign_EC_KEY(pkey, key);
246 case EVP_PKEY_DH:
247 return EVP_PKEY_assign_DH(pkey, key);
248 }
249
250 OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
251 ERR_add_error_dataf("algorithm %d", type);
252 return 0;
253 }
254
EVP_PKEY_set_type(EVP_PKEY * pkey,int type)255 int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) {
256 if (pkey && pkey->pkey) {
257 // This isn't strictly necessary, but historically |EVP_PKEY_set_type| would
258 // clear |pkey| even if |evp_pkey_asn1_find| failed, so we preserve that
259 // behavior.
260 free_it(pkey);
261 }
262
263 const EVP_PKEY_ASN1_METHOD *ameth = evp_pkey_asn1_find(type);
264 if (ameth == NULL) {
265 OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
266 ERR_add_error_dataf("algorithm %d", type);
267 return 0;
268 }
269
270 if (pkey) {
271 evp_pkey_set_method(pkey, ameth);
272 }
273
274 return 1;
275 }
276
EVP_PKEY_new_raw_private_key(int type,ENGINE * unused,const uint8_t * in,size_t len)277 EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *unused,
278 const uint8_t *in, size_t len) {
279 // To avoid pulling in all key types, look for specifically the key types that
280 // support |set_priv_raw|.
281 const EVP_PKEY_ASN1_METHOD *method;
282 switch (type) {
283 case EVP_PKEY_X25519:
284 method = &x25519_asn1_meth;
285 break;
286 case EVP_PKEY_ED25519:
287 method = &ed25519_asn1_meth;
288 break;
289 default:
290 OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
291 return 0;
292 }
293
294 EVP_PKEY *ret = EVP_PKEY_new();
295 if (ret == NULL) {
296 goto err;
297 }
298 evp_pkey_set_method(ret, method);
299
300 if (!ret->ameth->set_priv_raw(ret, in, len)) {
301 goto err;
302 }
303
304 return ret;
305
306 err:
307 EVP_PKEY_free(ret);
308 return NULL;
309 }
310
EVP_PKEY_new_raw_public_key(int type,ENGINE * unused,const uint8_t * in,size_t len)311 EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *unused,
312 const uint8_t *in, size_t len) {
313 // To avoid pulling in all key types, look for specifically the key types that
314 // support |set_pub_raw|.
315 const EVP_PKEY_ASN1_METHOD *method;
316 switch (type) {
317 case EVP_PKEY_X25519:
318 method = &x25519_asn1_meth;
319 break;
320 case EVP_PKEY_ED25519:
321 method = &ed25519_asn1_meth;
322 break;
323 default:
324 OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
325 return 0;
326 }
327
328 EVP_PKEY *ret = EVP_PKEY_new();
329 if (ret == NULL) {
330 goto err;
331 }
332 evp_pkey_set_method(ret, method);
333
334 if (!ret->ameth->set_pub_raw(ret, in, len)) {
335 goto err;
336 }
337
338 return ret;
339
340 err:
341 EVP_PKEY_free(ret);
342 return NULL;
343 }
344
EVP_PKEY_get_raw_private_key(const EVP_PKEY * pkey,uint8_t * out,size_t * out_len)345 int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, uint8_t *out,
346 size_t *out_len) {
347 if (pkey->ameth->get_priv_raw == NULL) {
348 OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
349 return 0;
350 }
351
352 return pkey->ameth->get_priv_raw(pkey, out, out_len);
353 }
354
EVP_PKEY_get_raw_public_key(const EVP_PKEY * pkey,uint8_t * out,size_t * out_len)355 int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, uint8_t *out,
356 size_t *out_len) {
357 if (pkey->ameth->get_pub_raw == NULL) {
358 OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
359 return 0;
360 }
361
362 return pkey->ameth->get_pub_raw(pkey, out, out_len);
363 }
364
EVP_PKEY_cmp_parameters(const EVP_PKEY * a,const EVP_PKEY * b)365 int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
366 if (a->type != b->type) {
367 return -1;
368 }
369 if (a->ameth && a->ameth->param_cmp) {
370 return a->ameth->param_cmp(a, b);
371 }
372 // TODO(https://crbug.com/boringssl/536): If the algorithm doesn't use
373 // parameters, they should compare as vacuously equal.
374 return -2;
375 }
376
EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX * ctx,const EVP_MD * md)377 int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
378 return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD, 0,
379 (void *)md);
380 }
381
EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX * ctx,const EVP_MD ** out_md)382 int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) {
383 return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_GET_MD,
384 0, (void *)out_md);
385 }
386
EVP_PKEY_get0(const EVP_PKEY * pkey)387 void *EVP_PKEY_get0(const EVP_PKEY *pkey) {
388 // Node references, but never calls this function, so for now we return NULL.
389 // If other projects require complete support, call |EVP_PKEY_get0_RSA|, etc.,
390 // rather than reading |pkey->pkey| directly. This avoids problems if our
391 // internal representation does not match the type the caller expects from
392 // OpenSSL.
393 return NULL;
394 }
395
OpenSSL_add_all_algorithms(void)396 void OpenSSL_add_all_algorithms(void) {}
397
OPENSSL_add_all_algorithms_conf(void)398 void OPENSSL_add_all_algorithms_conf(void) {}
399
OpenSSL_add_all_ciphers(void)400 void OpenSSL_add_all_ciphers(void) {}
401
OpenSSL_add_all_digests(void)402 void OpenSSL_add_all_digests(void) {}
403
EVP_cleanup(void)404 void EVP_cleanup(void) {}
405
EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY * pkey,const uint8_t * in,size_t len)406 int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey, const uint8_t *in,
407 size_t len) {
408 if (pkey->ameth->set1_tls_encodedpoint == NULL) {
409 OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
410 return 0;
411 }
412
413 return pkey->ameth->set1_tls_encodedpoint(pkey, in, len);
414 }
415
EVP_PKEY_get1_tls_encodedpoint(const EVP_PKEY * pkey,uint8_t ** out_ptr)416 size_t EVP_PKEY_get1_tls_encodedpoint(const EVP_PKEY *pkey, uint8_t **out_ptr) {
417 if (pkey->ameth->get1_tls_encodedpoint == NULL) {
418 OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
419 return 0;
420 }
421
422 return pkey->ameth->get1_tls_encodedpoint(pkey, out_ptr);
423 }
424
EVP_PKEY_base_id(const EVP_PKEY * pkey)425 int EVP_PKEY_base_id(const EVP_PKEY *pkey) {
426 // OpenSSL has two notions of key type because it supports multiple OIDs for
427 // the same algorithm: NID_rsa vs NID_rsaEncryption and five distinct spelling
428 // of DSA. We do not support these, so the base ID is simply the ID.
429 return EVP_PKEY_id(pkey);
430 }
431