blob: e71f82d8e21f85b0dc34055db0ba61b288dcb692 [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* 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
David Benjamin443a1f62015-09-04 15:05:05 -040057#include <openssl/ssl.h>
Adam Langley95c29f32014-06-20 12:00:00 -070058
David Benjamin3a596112015-11-12 09:25:30 -080059#include <limits.h>
60
Adam Langley95c29f32014-06-20 12:00:00 -070061#include <openssl/err.h>
62#include <openssl/evp.h>
63#include <openssl/mem.h>
David Benjamind246b812016-07-08 15:07:02 -070064#include <openssl/type_check.h>
Adam Langley95c29f32014-06-20 12:00:00 -070065#include <openssl/x509.h>
66
David Benjamin2ee94aa2015-04-07 22:38:30 -040067#include "internal.h"
Adam Langley95c29f32014-06-20 12:00:00 -070068
David Benjamin443a1f62015-09-04 15:05:05 -040069
Adam Langley95c29f32014-06-20 12:00:00 -070070static int ssl_set_cert(CERT *c, X509 *x509);
71static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey);
Adam Langley95c29f32014-06-20 12:00:00 -070072
David Benjamind1d80782015-07-05 11:54:09 -040073static int is_key_type_supported(int key_type) {
74 return key_type == EVP_PKEY_RSA || key_type == EVP_PKEY_EC;
75}
76
Adam Langleyfcf25832014-12-18 17:42:32 -080077int SSL_use_certificate(SSL *ssl, X509 *x) {
78 if (x == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -040079 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -080080 return 0;
81 }
Adam Langleyfcf25832014-12-18 17:42:32 -080082 return ssl_set_cert(ssl->cert, x);
83}
Adam Langley95c29f32014-06-20 12:00:00 -070084
David Benjamin3a596112015-11-12 09:25:30 -080085int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
86 if (der_len > LONG_MAX) {
87 OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
Adam Langleyfcf25832014-12-18 17:42:32 -080088 return 0;
89 }
90
David Benjamin3a596112015-11-12 09:25:30 -080091 const uint8_t *p = der;
92 X509 *x509 = d2i_X509(NULL, &p, (long)der_len);
93 if (x509 == NULL || p != der + der_len) {
94 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
95 X509_free(x509);
96 return 0;
97 }
98
99 int ret = SSL_use_certificate(ssl, x509);
100 X509_free(x509);
Adam Langleyfcf25832014-12-18 17:42:32 -0800101 return ret;
102}
103
104int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
105 EVP_PKEY *pkey;
106 int ret;
107
108 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400109 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800110 return 0;
111 }
112
Adam Langleyfcf25832014-12-18 17:42:32 -0800113 pkey = EVP_PKEY_new();
114 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400115 OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800116 return 0;
117 }
118
119 RSA_up_ref(rsa);
120 EVP_PKEY_assign_RSA(pkey, rsa);
121
122 ret = ssl_set_pkey(ssl->cert, pkey);
123 EVP_PKEY_free(pkey);
124
125 return ret;
126}
127
128static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) {
David Benjamind1d80782015-07-05 11:54:09 -0400129 if (!is_key_type_supported(pkey->type)) {
David Benjamin3570d732015-06-29 00:28:17 -0400130 OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
Adam Langleyfcf25832014-12-18 17:42:32 -0800131 return 0;
132 }
133
David Benjamind1d80782015-07-05 11:54:09 -0400134 if (c->x509 != NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800135 /* Sanity-check that the private key and the certificate match, unless the
136 * key is opaque (in case of, say, a smartcard). */
137 if (!EVP_PKEY_is_opaque(pkey) &&
David Benjamind1d80782015-07-05 11:54:09 -0400138 !X509_check_private_key(c->x509, pkey)) {
139 X509_free(c->x509);
140 c->x509 = NULL;
Adam Langleyfcf25832014-12-18 17:42:32 -0800141 return 0;
142 }
143 }
144
David Benjamind1d80782015-07-05 11:54:09 -0400145 EVP_PKEY_free(c->privatekey);
Adam Langley310d3f62016-07-12 10:39:20 -0700146 EVP_PKEY_up_ref(pkey);
147 c->privatekey = pkey;
Adam Langleyfcf25832014-12-18 17:42:32 -0800148
149 return 1;
150}
151
David Benjamin74f71102015-06-27 14:56:25 -0400152int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
153 RSA *rsa = RSA_private_key_from_bytes(der, der_len);
Adam Langleyfcf25832014-12-18 17:42:32 -0800154 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400155 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800156 return 0;
157 }
158
David Benjamin74f71102015-06-27 14:56:25 -0400159 int ret = SSL_use_RSAPrivateKey(ssl, rsa);
Adam Langleyfcf25832014-12-18 17:42:32 -0800160 RSA_free(rsa);
161 return ret;
162}
163
164int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) {
165 int ret;
166
167 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400168 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800169 return 0;
170 }
171
Adam Langleyfcf25832014-12-18 17:42:32 -0800172 ret = ssl_set_pkey(ssl->cert, pkey);
173 return ret;
174}
175
David Benjamin3a596112015-11-12 09:25:30 -0800176int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *der,
177 size_t der_len) {
178 if (der_len > LONG_MAX) {
179 OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
Adam Langleyfcf25832014-12-18 17:42:32 -0800180 return 0;
181 }
182
David Benjamin3a596112015-11-12 09:25:30 -0800183 const uint8_t *p = der;
184 EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len);
185 if (pkey == NULL || p != der + der_len) {
186 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
187 EVP_PKEY_free(pkey);
188 return 0;
189 }
190
191 int ret = SSL_use_PrivateKey(ssl, pkey);
Adam Langleyfcf25832014-12-18 17:42:32 -0800192 EVP_PKEY_free(pkey);
193 return ret;
194}
195
196int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) {
197 if (x == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400198 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800199 return 0;
200 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800201
202 return ssl_set_cert(ctx->cert, x);
203}
204
205static int ssl_set_cert(CERT *c, X509 *x) {
David Benjamind1d80782015-07-05 11:54:09 -0400206 EVP_PKEY *pkey = X509_get_pubkey(x);
Adam Langleyfcf25832014-12-18 17:42:32 -0800207 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400208 OPENSSL_PUT_ERROR(SSL, SSL_R_X509_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800209 return 0;
210 }
211
David Benjamind1d80782015-07-05 11:54:09 -0400212 if (!is_key_type_supported(pkey->type)) {
David Benjamin3570d732015-06-29 00:28:17 -0400213 OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
Adam Langleyfcf25832014-12-18 17:42:32 -0800214 EVP_PKEY_free(pkey);
215 return 0;
216 }
217
David Benjamind1d80782015-07-05 11:54:09 -0400218 if (c->privatekey != NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800219 /* Sanity-check that the private key and the certificate match, unless the
220 * key is opaque (in case of, say, a smartcard). */
David Benjamind1d80782015-07-05 11:54:09 -0400221 if (!EVP_PKEY_is_opaque(c->privatekey) &&
222 !X509_check_private_key(x, c->privatekey)) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800223 /* don't fail for a cert/key mismatch, just free current private key
224 * (when switching to a different cert & key, first this function should
225 * be used, then ssl_set_pkey */
David Benjamind1d80782015-07-05 11:54:09 -0400226 EVP_PKEY_free(c->privatekey);
227 c->privatekey = NULL;
Adam Langleyfcf25832014-12-18 17:42:32 -0800228 /* clear error queue */
229 ERR_clear_error();
230 }
231 }
232
233 EVP_PKEY_free(pkey);
234
David Benjamind1d80782015-07-05 11:54:09 -0400235 X509_free(c->x509);
236 c->x509 = X509_up_ref(x);
Adam Langleyfcf25832014-12-18 17:42:32 -0800237
238 return 1;
239}
240
David Benjamin3a596112015-11-12 09:25:30 -0800241int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len,
242 const uint8_t *der) {
243 if (der_len > LONG_MAX) {
244 OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
Adam Langleyfcf25832014-12-18 17:42:32 -0800245 return 0;
246 }
247
David Benjamin3a596112015-11-12 09:25:30 -0800248 const uint8_t *p = der;
249 X509 *x509 = d2i_X509(NULL, &p, (long)der_len);
250 if (x509 == NULL || p != der + der_len) {
251 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
252 X509_free(x509);
253 return 0;
254 }
255
256 int ret = SSL_CTX_use_certificate(ctx, x509);
257 X509_free(x509);
Adam Langleyfcf25832014-12-18 17:42:32 -0800258 return ret;
259}
260
261int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) {
262 int ret;
263 EVP_PKEY *pkey;
264
265 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400266 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800267 return 0;
268 }
269
Adam Langleyfcf25832014-12-18 17:42:32 -0800270 pkey = EVP_PKEY_new();
271 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400272 OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800273 return 0;
274 }
275
276 RSA_up_ref(rsa);
277 EVP_PKEY_assign_RSA(pkey, rsa);
278
279 ret = ssl_set_pkey(ctx->cert, pkey);
280 EVP_PKEY_free(pkey);
281 return ret;
282}
283
David Benjamin74f71102015-06-27 14:56:25 -0400284int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *der,
285 size_t der_len) {
286 RSA *rsa = RSA_private_key_from_bytes(der, der_len);
Adam Langleyfcf25832014-12-18 17:42:32 -0800287 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400288 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800289 return 0;
290 }
291
David Benjamin74f71102015-06-27 14:56:25 -0400292 int ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
Adam Langleyfcf25832014-12-18 17:42:32 -0800293 RSA_free(rsa);
294 return ret;
295}
296
297int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) {
298 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400299 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800300 return 0;
301 }
302
Adam Langleyfcf25832014-12-18 17:42:32 -0800303 return ssl_set_pkey(ctx->cert, pkey);
304}
305
David Benjamin3a596112015-11-12 09:25:30 -0800306int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *der,
307 size_t der_len) {
308 if (der_len > LONG_MAX) {
309 OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
Adam Langleyfcf25832014-12-18 17:42:32 -0800310 return 0;
311 }
312
David Benjamin3a596112015-11-12 09:25:30 -0800313 const uint8_t *p = der;
314 EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len);
315 if (pkey == NULL || p != der + der_len) {
316 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
317 EVP_PKEY_free(pkey);
318 return 0;
319 }
320
321 int ret = SSL_CTX_use_PrivateKey(ctx, pkey);
Adam Langleyfcf25832014-12-18 17:42:32 -0800322 EVP_PKEY_free(pkey);
323 return ret;
324}
325
David Benjaminb4d65fd2015-05-29 17:11:21 -0400326void SSL_set_private_key_method(SSL *ssl,
327 const SSL_PRIVATE_KEY_METHOD *key_method) {
328 ssl->cert->key_method = key_method;
329}
330
Tom Thorogood66b2fe82016-03-06 20:08:38 +1030331void SSL_CTX_set_private_key_method(SSL_CTX *ctx,
332 const SSL_PRIVATE_KEY_METHOD *key_method) {
333 ctx->cert->key_method = key_method;
334}
335
David Benjamind246b812016-07-08 15:07:02 -0700336OPENSSL_COMPILE_ASSERT(sizeof(int) >= 2 * sizeof(uint16_t),
337 digest_list_conversion_cannot_overflow);
338
Steven Valdez0d62f262015-09-04 12:41:04 -0400339int SSL_set_private_key_digest_prefs(SSL *ssl, const int *digest_nids,
340 size_t num_digests) {
David Benjamind246b812016-07-08 15:07:02 -0700341 OPENSSL_free(ssl->cert->sigalgs);
Steven Valdez0d62f262015-09-04 12:41:04 -0400342
David Benjamind246b812016-07-08 15:07:02 -0700343 ssl->cert->sigalgs_len = 0;
344 ssl->cert->sigalgs = OPENSSL_malloc(sizeof(uint16_t) * 2 * num_digests);
345 if (ssl->cert->sigalgs == NULL) {
Steven Valdez0d62f262015-09-04 12:41:04 -0400346 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
347 return 0;
348 }
349
David Benjamind246b812016-07-08 15:07:02 -0700350 /* Convert the digest list to a signature algorithms list.
351 *
352 * TODO(davidben): Replace this API with one that can express RSA-PSS, etc. */
353 for (size_t i = 0; i < num_digests; i++) {
354 switch (digest_nids[i]) {
355 case NID_sha1:
356 ssl->cert->sigalgs[ssl->cert->sigalgs_len] = SSL_SIGN_RSA_PKCS1_SHA1;
357 ssl->cert->sigalgs[ssl->cert->sigalgs_len + 1] = SSL_SIGN_ECDSA_SHA1;
358 ssl->cert->sigalgs_len += 2;
359 break;
360 case NID_sha256:
361 ssl->cert->sigalgs[ssl->cert->sigalgs_len] = SSL_SIGN_RSA_PKCS1_SHA256;
362 ssl->cert->sigalgs[ssl->cert->sigalgs_len + 1] =
363 SSL_SIGN_ECDSA_SECP256R1_SHA256;
364 ssl->cert->sigalgs_len += 2;
365 break;
366 case NID_sha384:
367 ssl->cert->sigalgs[ssl->cert->sigalgs_len] = SSL_SIGN_RSA_PKCS1_SHA384;
368 ssl->cert->sigalgs[ssl->cert->sigalgs_len + 1] =
369 SSL_SIGN_ECDSA_SECP384R1_SHA384;
370 ssl->cert->sigalgs_len += 2;
371 break;
372 case NID_sha512:
373 ssl->cert->sigalgs[ssl->cert->sigalgs_len] = SSL_SIGN_RSA_PKCS1_SHA512;
374 ssl->cert->sigalgs[ssl->cert->sigalgs_len + 1] =
375 SSL_SIGN_ECDSA_SECP521R1_SHA512;
376 ssl->cert->sigalgs_len += 2;
377 break;
378 }
379 }
380
Steven Valdez0d62f262015-09-04 12:41:04 -0400381 return 1;
382}
383
nagendra modadugu601448a2015-07-24 09:31:31 -0700384int ssl_has_private_key(SSL *ssl) {
385 return ssl->cert->privatekey != NULL || ssl->cert->key_method != NULL;
386}
387
David Benjamind1d80782015-07-05 11:54:09 -0400388int ssl_private_key_type(SSL *ssl) {
David Benjaminb4d65fd2015-05-29 17:11:21 -0400389 if (ssl->cert->key_method != NULL) {
390 return ssl->cert->key_method->type(ssl);
391 }
David Benjamind1d80782015-07-05 11:54:09 -0400392 return EVP_PKEY_id(ssl->cert->privatekey);
David Benjaminb4d65fd2015-05-29 17:11:21 -0400393}
394
David Benjamind1d80782015-07-05 11:54:09 -0400395size_t ssl_private_key_max_signature_len(SSL *ssl) {
David Benjaminb4d65fd2015-05-29 17:11:21 -0400396 if (ssl->cert->key_method != NULL) {
397 return ssl->cert->key_method->max_signature_len(ssl);
398 }
David Benjamind1d80782015-07-05 11:54:09 -0400399 return EVP_PKEY_size(ssl->cert->privatekey);
David Benjaminb4d65fd2015-05-29 17:11:21 -0400400}
401
David Benjamina2d81f12016-07-08 15:42:16 -0700402static int is_rsa_pkcs1(const EVP_MD **out_md, uint16_t sigalg) {
403 switch (sigalg) {
404 case SSL_SIGN_RSA_PKCS1_MD5_SHA1:
405 *out_md = EVP_md5_sha1();
406 return 1;
407 case SSL_SIGN_RSA_PKCS1_SHA1:
408 *out_md = EVP_sha1();
409 return 1;
410 case SSL_SIGN_RSA_PKCS1_SHA256:
411 *out_md = EVP_sha256();
412 return 1;
413 case SSL_SIGN_RSA_PKCS1_SHA384:
414 *out_md = EVP_sha384();
415 return 1;
416 case SSL_SIGN_RSA_PKCS1_SHA512:
417 *out_md = EVP_sha512();
418 return 1;
David Benjamind246b812016-07-08 15:07:02 -0700419 default:
David Benjamina2d81f12016-07-08 15:42:16 -0700420 return 0;
David Benjamind246b812016-07-08 15:07:02 -0700421 }
422}
423
David Benjamina2d81f12016-07-08 15:42:16 -0700424static int ssl_sign_rsa_pkcs1(SSL *ssl, uint8_t *out, size_t *out_len,
425 size_t max_out, const EVP_MD *md,
426 const uint8_t *in, size_t in_len) {
427 EVP_MD_CTX ctx;
428 EVP_MD_CTX_init(&ctx);
429 *out_len = max_out;
430 int ret = EVP_DigestSignInit(&ctx, NULL, md, NULL, ssl->cert->privatekey) &&
431 EVP_DigestSignUpdate(&ctx, in, in_len) &&
432 EVP_DigestSignFinal(&ctx, out, out_len);
433 EVP_MD_CTX_cleanup(&ctx);
434 return ret;
435}
436
437static int ssl_verify_rsa_pkcs1(SSL *ssl, const uint8_t *signature,
438 size_t signature_len, const EVP_MD *md,
439 EVP_PKEY *pkey, const uint8_t *in,
440 size_t in_len) {
David Benjamin887c3002016-07-08 16:15:32 -0700441 if (pkey->type != EVP_PKEY_RSA) {
442 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
443 return 0;
444 }
445
David Benjamina2d81f12016-07-08 15:42:16 -0700446 EVP_MD_CTX md_ctx;
447 EVP_MD_CTX_init(&md_ctx);
448 int ret = EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) &&
449 EVP_DigestVerifyUpdate(&md_ctx, in, in_len) &&
450 EVP_DigestVerifyFinal(&md_ctx, signature, signature_len);
451 EVP_MD_CTX_cleanup(&md_ctx);
452 return ret;
453}
454
455static int is_ecdsa(const EVP_MD **out_md, uint16_t sigalg) {
456 switch (sigalg) {
457 case SSL_SIGN_ECDSA_SHA1:
458 *out_md = EVP_sha1();
459 return 1;
460 case SSL_SIGN_ECDSA_SECP256R1_SHA256:
461 *out_md = EVP_sha256();
462 return 1;
463 case SSL_SIGN_ECDSA_SECP384R1_SHA384:
464 *out_md = EVP_sha384();
465 return 1;
466 case SSL_SIGN_ECDSA_SECP521R1_SHA512:
467 *out_md = EVP_sha512();
468 return 1;
469 default:
470 return 0;
471 }
472}
473
474static int ssl_sign_ecdsa(SSL *ssl, uint8_t *out, size_t *out_len,
475 size_t max_out, const EVP_MD *md, const uint8_t *in,
476 size_t in_len) {
477 EVP_MD_CTX ctx;
478 EVP_MD_CTX_init(&ctx);
479 *out_len = max_out;
480 int ret = EVP_DigestSignInit(&ctx, NULL, md, NULL, ssl->cert->privatekey) &&
481 EVP_DigestSignUpdate(&ctx, in, in_len) &&
482 EVP_DigestSignFinal(&ctx, out, out_len);
483 EVP_MD_CTX_cleanup(&ctx);
484 return ret;
485}
486
487static int ssl_verify_ecdsa(SSL *ssl, const uint8_t *signature,
488 size_t signature_len, const EVP_MD *md,
489 EVP_PKEY *pkey, const uint8_t *in, size_t in_len) {
David Benjamin887c3002016-07-08 16:15:32 -0700490 if (pkey->type != EVP_PKEY_EC) {
491 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
492 return 0;
493 }
494
David Benjamina2d81f12016-07-08 15:42:16 -0700495 EVP_MD_CTX md_ctx;
496 EVP_MD_CTX_init(&md_ctx);
497 int ret = EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) &&
498 EVP_DigestVerifyUpdate(&md_ctx, in, in_len) &&
499 EVP_DigestVerifyFinal(&md_ctx, signature, signature_len);
500 EVP_MD_CTX_cleanup(&md_ctx);
501 return ret;
502}
503
David Benjaminb4d65fd2015-05-29 17:11:21 -0400504enum ssl_private_key_result_t ssl_private_key_sign(
Steven Valdezf0451ca2016-06-29 13:16:27 -0400505 SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
506 uint16_t signature_algorithm, const uint8_t *in, size_t in_len) {
David Benjaminb4d65fd2015-05-29 17:11:21 -0400507 if (ssl->cert->key_method != NULL) {
David Benjamina2d81f12016-07-08 15:42:16 -0700508 /* For now, custom private keys can only handle pre-TLS-1.3 signature
509 * algorithms.
510 *
511 * TODO(davidben): Switch SSL_PRIVATE_KEY_METHOD to message-based APIs. */
512 const EVP_MD *md;
513 if (!is_rsa_pkcs1(&md, signature_algorithm) &&
514 !is_ecdsa(&md, signature_algorithm)) {
515 OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
516 return ssl_private_key_failure;
517 }
518
519 uint8_t hash[EVP_MAX_MD_SIZE];
520 unsigned hash_len;
521 if (!EVP_Digest(in, in_len, hash, &hash_len, md, NULL)) {
522 return ssl_private_key_failure;
523 }
524
Steven Valdez2b8415e2016-06-30 13:27:23 -0400525 return ssl->cert->key_method->sign(ssl, out, out_len, max_out, md, hash,
526 hash_len);
David Benjaminb4d65fd2015-05-29 17:11:21 -0400527 }
528
David Benjamina2d81f12016-07-08 15:42:16 -0700529 const EVP_MD *md;
530 if (is_rsa_pkcs1(&md, signature_algorithm)) {
531 return ssl_sign_rsa_pkcs1(ssl, out, out_len, max_out, md, in, in_len)
532 ? ssl_private_key_success
533 : ssl_private_key_failure;
534 }
535 if (is_ecdsa(&md, signature_algorithm)) {
536 return ssl_sign_ecdsa(ssl, out, out_len, max_out, md, in, in_len)
537 ? ssl_private_key_success
538 : ssl_private_key_failure;
David Benjaminb4d65fd2015-05-29 17:11:21 -0400539 }
540
David Benjamina2d81f12016-07-08 15:42:16 -0700541 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
542 return ssl_private_key_failure;
David Benjaminb4d65fd2015-05-29 17:11:21 -0400543}
544
545enum ssl_private_key_result_t ssl_private_key_sign_complete(
546 SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) {
547 /* Only custom keys may be asynchronous. */
548 return ssl->cert->key_method->sign_complete(ssl, out, out_len, max_out);
549}
nagendra modadugu3398dbf2015-08-07 14:07:52 -0700550
Steven Valdez2b8415e2016-06-30 13:27:23 -0400551int ssl_public_key_verify(SSL *ssl, const uint8_t *signature,
552 size_t signature_len, uint16_t signature_algorithm,
553 EVP_PKEY *pkey, const uint8_t *in, size_t in_len) {
David Benjamina2d81f12016-07-08 15:42:16 -0700554 const EVP_MD *md;
555 if (is_rsa_pkcs1(&md, signature_algorithm)) {
556 return ssl_verify_rsa_pkcs1(ssl, signature, signature_len, md, pkey, in,
557 in_len);
558 }
559 if (is_ecdsa(&md, signature_algorithm)) {
560 return ssl_verify_ecdsa(ssl, signature, signature_len, md, pkey, in,
561 in_len);
Steven Valdez2b8415e2016-06-30 13:27:23 -0400562 }
563
David Benjamina2d81f12016-07-08 15:42:16 -0700564 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
565 return 0;
Steven Valdez2b8415e2016-06-30 13:27:23 -0400566}
567
nagendra modadugu3398dbf2015-08-07 14:07:52 -0700568enum ssl_private_key_result_t ssl_private_key_decrypt(
569 SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
570 const uint8_t *in, size_t in_len) {
571 if (ssl->cert->key_method != NULL) {
572 return ssl->cert->key_method->decrypt(ssl, out, out_len, max_out, in,
573 in_len);
574 }
575
David Benjamin758d1272015-11-20 17:47:25 -0500576 RSA *rsa = EVP_PKEY_get0_RSA(ssl->cert->privatekey);
577 if (rsa == NULL) {
nagendra modadugu3398dbf2015-08-07 14:07:52 -0700578 /* Decrypt operations are only supported for RSA keys. */
579 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
580 return ssl_private_key_failure;
581 }
582
nagendra modadugu3398dbf2015-08-07 14:07:52 -0700583 /* Decrypt with no padding. PKCS#1 padding will be removed as part
584 * of the timing-sensitive code by the caller. */
David Benjamin758d1272015-11-20 17:47:25 -0500585 if (!RSA_decrypt(rsa, out_len, out, max_out, in, in_len, RSA_NO_PADDING)) {
586 return ssl_private_key_failure;
nagendra modadugu3398dbf2015-08-07 14:07:52 -0700587 }
David Benjamin758d1272015-11-20 17:47:25 -0500588 return ssl_private_key_success;
nagendra modadugu3398dbf2015-08-07 14:07:52 -0700589}
590
591enum ssl_private_key_result_t ssl_private_key_decrypt_complete(
592 SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) {
593 /* Only custom keys may be asynchronous. */
594 return ssl->cert->key_method->decrypt_complete(ssl, out, out_len, max_out);
595}