blob: a5f15f459f506c7a9251a9d92159f993fb4baef6 [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
David Benjamin1fb125c2016-07-08 18:52:12 -070061#include <openssl/ec.h>
62#include <openssl/ec_key.h>
Adam Langley95c29f32014-06-20 12:00:00 -070063#include <openssl/err.h>
64#include <openssl/evp.h>
65#include <openssl/mem.h>
David Benjamind246b812016-07-08 15:07:02 -070066#include <openssl/type_check.h>
Adam Langley95c29f32014-06-20 12:00:00 -070067#include <openssl/x509.h>
68
David Benjamin2ee94aa2015-04-07 22:38:30 -040069#include "internal.h"
Adam Langley95c29f32014-06-20 12:00:00 -070070
David Benjamin443a1f62015-09-04 15:05:05 -040071
Adam Langley95c29f32014-06-20 12:00:00 -070072static int ssl_set_cert(CERT *c, X509 *x509);
73static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey);
Adam Langley95c29f32014-06-20 12:00:00 -070074
David Benjamind1d80782015-07-05 11:54:09 -040075static int is_key_type_supported(int key_type) {
76 return key_type == EVP_PKEY_RSA || key_type == EVP_PKEY_EC;
77}
78
Adam Langleyfcf25832014-12-18 17:42:32 -080079int SSL_use_certificate(SSL *ssl, X509 *x) {
80 if (x == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -040081 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -080082 return 0;
83 }
Adam Langleyfcf25832014-12-18 17:42:32 -080084 return ssl_set_cert(ssl->cert, x);
85}
Adam Langley95c29f32014-06-20 12:00:00 -070086
David Benjamin3a596112015-11-12 09:25:30 -080087int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
88 if (der_len > LONG_MAX) {
89 OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
Adam Langleyfcf25832014-12-18 17:42:32 -080090 return 0;
91 }
92
David Benjamin3a596112015-11-12 09:25:30 -080093 const uint8_t *p = der;
94 X509 *x509 = d2i_X509(NULL, &p, (long)der_len);
95 if (x509 == NULL || p != der + der_len) {
96 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
97 X509_free(x509);
98 return 0;
99 }
100
101 int ret = SSL_use_certificate(ssl, x509);
102 X509_free(x509);
Adam Langleyfcf25832014-12-18 17:42:32 -0800103 return ret;
104}
105
106int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
107 EVP_PKEY *pkey;
108 int ret;
109
110 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400111 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800112 return 0;
113 }
114
Adam Langleyfcf25832014-12-18 17:42:32 -0800115 pkey = EVP_PKEY_new();
116 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400117 OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800118 return 0;
119 }
120
121 RSA_up_ref(rsa);
122 EVP_PKEY_assign_RSA(pkey, rsa);
123
124 ret = ssl_set_pkey(ssl->cert, pkey);
125 EVP_PKEY_free(pkey);
126
127 return ret;
128}
129
130static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) {
David Benjamind1d80782015-07-05 11:54:09 -0400131 if (!is_key_type_supported(pkey->type)) {
David Benjamin3570d732015-06-29 00:28:17 -0400132 OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
Adam Langleyfcf25832014-12-18 17:42:32 -0800133 return 0;
134 }
135
David Benjamind1d80782015-07-05 11:54:09 -0400136 if (c->x509 != NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800137 /* Sanity-check that the private key and the certificate match, unless the
138 * key is opaque (in case of, say, a smartcard). */
139 if (!EVP_PKEY_is_opaque(pkey) &&
David Benjamind1d80782015-07-05 11:54:09 -0400140 !X509_check_private_key(c->x509, pkey)) {
141 X509_free(c->x509);
142 c->x509 = NULL;
Adam Langleyfcf25832014-12-18 17:42:32 -0800143 return 0;
144 }
145 }
146
David Benjamind1d80782015-07-05 11:54:09 -0400147 EVP_PKEY_free(c->privatekey);
Adam Langley310d3f62016-07-12 10:39:20 -0700148 EVP_PKEY_up_ref(pkey);
149 c->privatekey = pkey;
Adam Langleyfcf25832014-12-18 17:42:32 -0800150
151 return 1;
152}
153
David Benjamin74f71102015-06-27 14:56:25 -0400154int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
155 RSA *rsa = RSA_private_key_from_bytes(der, der_len);
Adam Langleyfcf25832014-12-18 17:42:32 -0800156 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400157 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800158 return 0;
159 }
160
David Benjamin74f71102015-06-27 14:56:25 -0400161 int ret = SSL_use_RSAPrivateKey(ssl, rsa);
Adam Langleyfcf25832014-12-18 17:42:32 -0800162 RSA_free(rsa);
163 return ret;
164}
165
166int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) {
167 int ret;
168
169 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400170 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800171 return 0;
172 }
173
Adam Langleyfcf25832014-12-18 17:42:32 -0800174 ret = ssl_set_pkey(ssl->cert, pkey);
175 return ret;
176}
177
David Benjamin3a596112015-11-12 09:25:30 -0800178int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *der,
179 size_t der_len) {
180 if (der_len > LONG_MAX) {
181 OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
Adam Langleyfcf25832014-12-18 17:42:32 -0800182 return 0;
183 }
184
David Benjamin3a596112015-11-12 09:25:30 -0800185 const uint8_t *p = der;
186 EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len);
187 if (pkey == NULL || p != der + der_len) {
188 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
189 EVP_PKEY_free(pkey);
190 return 0;
191 }
192
193 int ret = SSL_use_PrivateKey(ssl, pkey);
Adam Langleyfcf25832014-12-18 17:42:32 -0800194 EVP_PKEY_free(pkey);
195 return ret;
196}
197
198int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) {
199 if (x == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400200 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800201 return 0;
202 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800203
204 return ssl_set_cert(ctx->cert, x);
205}
206
207static int ssl_set_cert(CERT *c, X509 *x) {
David Benjamind1d80782015-07-05 11:54:09 -0400208 EVP_PKEY *pkey = X509_get_pubkey(x);
Adam Langleyfcf25832014-12-18 17:42:32 -0800209 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400210 OPENSSL_PUT_ERROR(SSL, SSL_R_X509_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800211 return 0;
212 }
213
David Benjamind1d80782015-07-05 11:54:09 -0400214 if (!is_key_type_supported(pkey->type)) {
David Benjamin3570d732015-06-29 00:28:17 -0400215 OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
Adam Langleyfcf25832014-12-18 17:42:32 -0800216 EVP_PKEY_free(pkey);
217 return 0;
218 }
219
David Benjamind1d80782015-07-05 11:54:09 -0400220 if (c->privatekey != NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800221 /* Sanity-check that the private key and the certificate match, unless the
222 * key is opaque (in case of, say, a smartcard). */
David Benjamind1d80782015-07-05 11:54:09 -0400223 if (!EVP_PKEY_is_opaque(c->privatekey) &&
224 !X509_check_private_key(x, c->privatekey)) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800225 /* don't fail for a cert/key mismatch, just free current private key
226 * (when switching to a different cert & key, first this function should
227 * be used, then ssl_set_pkey */
David Benjamind1d80782015-07-05 11:54:09 -0400228 EVP_PKEY_free(c->privatekey);
229 c->privatekey = NULL;
Adam Langleyfcf25832014-12-18 17:42:32 -0800230 /* clear error queue */
231 ERR_clear_error();
232 }
233 }
234
235 EVP_PKEY_free(pkey);
236
David Benjamind1d80782015-07-05 11:54:09 -0400237 X509_free(c->x509);
David Benjamin96a16cd2016-08-11 12:14:47 -0400238 X509_up_ref(x);
239 c->x509 = x;
Adam Langleyfcf25832014-12-18 17:42:32 -0800240
241 return 1;
242}
243
David Benjamin3a596112015-11-12 09:25:30 -0800244int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len,
245 const uint8_t *der) {
246 if (der_len > LONG_MAX) {
247 OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
Adam Langleyfcf25832014-12-18 17:42:32 -0800248 return 0;
249 }
250
David Benjamin3a596112015-11-12 09:25:30 -0800251 const uint8_t *p = der;
252 X509 *x509 = d2i_X509(NULL, &p, (long)der_len);
253 if (x509 == NULL || p != der + der_len) {
254 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
255 X509_free(x509);
256 return 0;
257 }
258
259 int ret = SSL_CTX_use_certificate(ctx, x509);
260 X509_free(x509);
Adam Langleyfcf25832014-12-18 17:42:32 -0800261 return ret;
262}
263
264int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) {
265 int ret;
266 EVP_PKEY *pkey;
267
268 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400269 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800270 return 0;
271 }
272
Adam Langleyfcf25832014-12-18 17:42:32 -0800273 pkey = EVP_PKEY_new();
274 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400275 OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800276 return 0;
277 }
278
279 RSA_up_ref(rsa);
280 EVP_PKEY_assign_RSA(pkey, rsa);
281
282 ret = ssl_set_pkey(ctx->cert, pkey);
283 EVP_PKEY_free(pkey);
284 return ret;
285}
286
David Benjamin74f71102015-06-27 14:56:25 -0400287int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *der,
288 size_t der_len) {
289 RSA *rsa = RSA_private_key_from_bytes(der, der_len);
Adam Langleyfcf25832014-12-18 17:42:32 -0800290 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400291 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800292 return 0;
293 }
294
David Benjamin74f71102015-06-27 14:56:25 -0400295 int ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
Adam Langleyfcf25832014-12-18 17:42:32 -0800296 RSA_free(rsa);
297 return ret;
298}
299
300int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) {
301 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400302 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800303 return 0;
304 }
305
Adam Langleyfcf25832014-12-18 17:42:32 -0800306 return ssl_set_pkey(ctx->cert, pkey);
307}
308
David Benjamin3a596112015-11-12 09:25:30 -0800309int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *der,
310 size_t der_len) {
311 if (der_len > LONG_MAX) {
312 OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
Adam Langleyfcf25832014-12-18 17:42:32 -0800313 return 0;
314 }
315
David Benjamin3a596112015-11-12 09:25:30 -0800316 const uint8_t *p = der;
317 EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len);
318 if (pkey == NULL || p != der + der_len) {
319 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
320 EVP_PKEY_free(pkey);
321 return 0;
322 }
323
324 int ret = SSL_CTX_use_PrivateKey(ctx, pkey);
Adam Langleyfcf25832014-12-18 17:42:32 -0800325 EVP_PKEY_free(pkey);
326 return ret;
327}
328
David Benjaminb4d65fd2015-05-29 17:11:21 -0400329void SSL_set_private_key_method(SSL *ssl,
330 const SSL_PRIVATE_KEY_METHOD *key_method) {
331 ssl->cert->key_method = key_method;
332}
333
Tom Thorogood66b2fe82016-03-06 20:08:38 +1030334void SSL_CTX_set_private_key_method(SSL_CTX *ctx,
335 const SSL_PRIVATE_KEY_METHOD *key_method) {
336 ctx->cert->key_method = key_method;
337}
338
David Benjamin0fc37ef2016-08-17 15:29:46 -0400339static int set_signing_algorithm_prefs(CERT *cert, const uint16_t *prefs,
340 size_t num_prefs) {
341 cert->num_sigalgs = 0;
342 cert->sigalgs = BUF_memdup(prefs, num_prefs * sizeof(prefs[0]));
343 if (cert->sigalgs == NULL) {
David Benjaminca3d5452016-07-14 12:51:01 -0400344 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
345 return 0;
346 }
David Benjamin0fc37ef2016-08-17 15:29:46 -0400347 cert->num_sigalgs = num_prefs;
David Benjaminca3d5452016-07-14 12:51:01 -0400348
349 return 1;
350}
351
David Benjamin0fc37ef2016-08-17 15:29:46 -0400352int SSL_CTX_set_signing_algorithm_prefs(SSL_CTX *ctx, const uint16_t *prefs,
353 size_t num_prefs) {
354 return set_signing_algorithm_prefs(ctx->cert, prefs, num_prefs);
355}
356
357
358int SSL_set_signing_algorithm_prefs(SSL *ssl, const uint16_t *prefs,
359 size_t num_prefs) {
360 return set_signing_algorithm_prefs(ssl->cert, prefs, num_prefs);
361}
362
David Benjamind246b812016-07-08 15:07:02 -0700363OPENSSL_COMPILE_ASSERT(sizeof(int) >= 2 * sizeof(uint16_t),
364 digest_list_conversion_cannot_overflow);
365
Steven Valdez0d62f262015-09-04 12:41:04 -0400366int SSL_set_private_key_digest_prefs(SSL *ssl, const int *digest_nids,
367 size_t num_digests) {
David Benjamind246b812016-07-08 15:07:02 -0700368 OPENSSL_free(ssl->cert->sigalgs);
Steven Valdez0d62f262015-09-04 12:41:04 -0400369
David Benjamin0fc37ef2016-08-17 15:29:46 -0400370 ssl->cert->num_sigalgs = 0;
David Benjamind246b812016-07-08 15:07:02 -0700371 ssl->cert->sigalgs = OPENSSL_malloc(sizeof(uint16_t) * 2 * num_digests);
372 if (ssl->cert->sigalgs == NULL) {
Steven Valdez0d62f262015-09-04 12:41:04 -0400373 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
374 return 0;
375 }
376
David Benjamind246b812016-07-08 15:07:02 -0700377 /* Convert the digest list to a signature algorithms list.
378 *
379 * TODO(davidben): Replace this API with one that can express RSA-PSS, etc. */
380 for (size_t i = 0; i < num_digests; i++) {
381 switch (digest_nids[i]) {
382 case NID_sha1:
David Benjamin0fc37ef2016-08-17 15:29:46 -0400383 ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA1;
384 ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] = SSL_SIGN_ECDSA_SHA1;
385 ssl->cert->num_sigalgs += 2;
David Benjamind246b812016-07-08 15:07:02 -0700386 break;
387 case NID_sha256:
David Benjamin0fc37ef2016-08-17 15:29:46 -0400388 ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA256;
389 ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] =
David Benjamind246b812016-07-08 15:07:02 -0700390 SSL_SIGN_ECDSA_SECP256R1_SHA256;
David Benjamin0fc37ef2016-08-17 15:29:46 -0400391 ssl->cert->num_sigalgs += 2;
David Benjamind246b812016-07-08 15:07:02 -0700392 break;
393 case NID_sha384:
David Benjamin0fc37ef2016-08-17 15:29:46 -0400394 ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA384;
395 ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] =
David Benjamind246b812016-07-08 15:07:02 -0700396 SSL_SIGN_ECDSA_SECP384R1_SHA384;
David Benjamin0fc37ef2016-08-17 15:29:46 -0400397 ssl->cert->num_sigalgs += 2;
David Benjamind246b812016-07-08 15:07:02 -0700398 break;
399 case NID_sha512:
David Benjamin0fc37ef2016-08-17 15:29:46 -0400400 ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA512;
401 ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] =
David Benjamind246b812016-07-08 15:07:02 -0700402 SSL_SIGN_ECDSA_SECP521R1_SHA512;
David Benjamin0fc37ef2016-08-17 15:29:46 -0400403 ssl->cert->num_sigalgs += 2;
David Benjamind246b812016-07-08 15:07:02 -0700404 break;
405 }
406 }
407
Steven Valdez0d62f262015-09-04 12:41:04 -0400408 return 1;
409}
410
David Benjamin32a66d52016-07-13 22:03:11 -0400411int ssl_has_private_key(const SSL *ssl) {
nagendra modadugu601448a2015-07-24 09:31:31 -0700412 return ssl->cert->privatekey != NULL || ssl->cert->key_method != NULL;
413}
414
David Benjamin0c0b7e12016-07-14 13:47:55 -0400415int ssl_is_ecdsa_key_type(int type) {
416 switch (type) {
417 /* TODO(davidben): Remove support for |EVP_PKEY_EC| key types. */
418 case EVP_PKEY_EC:
419 case NID_X9_62_prime256v1:
420 case NID_secp384r1:
421 case NID_secp521r1:
422 return 1;
423 default:
424 return 0;
425 }
426}
427
David Benjamind1d80782015-07-05 11:54:09 -0400428int ssl_private_key_type(SSL *ssl) {
David Benjaminb4d65fd2015-05-29 17:11:21 -0400429 if (ssl->cert->key_method != NULL) {
430 return ssl->cert->key_method->type(ssl);
431 }
David Benjamin0c0b7e12016-07-14 13:47:55 -0400432 switch (EVP_PKEY_id(ssl->cert->privatekey)) {
433 case EVP_PKEY_RSA:
434 return NID_rsaEncryption;
435 case EVP_PKEY_EC:
436 return EC_GROUP_get_curve_name(
437 EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(ssl->cert->privatekey)));
438 default:
439 return NID_undef;
440 }
David Benjaminb4d65fd2015-05-29 17:11:21 -0400441}
442
David Benjamind1d80782015-07-05 11:54:09 -0400443size_t ssl_private_key_max_signature_len(SSL *ssl) {
David Benjaminb4d65fd2015-05-29 17:11:21 -0400444 if (ssl->cert->key_method != NULL) {
445 return ssl->cert->key_method->max_signature_len(ssl);
446 }
David Benjamind1d80782015-07-05 11:54:09 -0400447 return EVP_PKEY_size(ssl->cert->privatekey);
David Benjaminb4d65fd2015-05-29 17:11:21 -0400448}
449
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400450/* TODO(davidben): Forbid RSA-PKCS1 in TLS 1.3. For now we allow it because NSS
451 * has yet to start doing RSA-PSS, so enforcing it would complicate interop
452 * testing. */
David Benjamina2d81f12016-07-08 15:42:16 -0700453static int is_rsa_pkcs1(const EVP_MD **out_md, uint16_t sigalg) {
454 switch (sigalg) {
455 case SSL_SIGN_RSA_PKCS1_MD5_SHA1:
456 *out_md = EVP_md5_sha1();
457 return 1;
458 case SSL_SIGN_RSA_PKCS1_SHA1:
459 *out_md = EVP_sha1();
460 return 1;
461 case SSL_SIGN_RSA_PKCS1_SHA256:
462 *out_md = EVP_sha256();
463 return 1;
464 case SSL_SIGN_RSA_PKCS1_SHA384:
465 *out_md = EVP_sha384();
466 return 1;
467 case SSL_SIGN_RSA_PKCS1_SHA512:
468 *out_md = EVP_sha512();
469 return 1;
David Benjamind246b812016-07-08 15:07:02 -0700470 default:
David Benjamina2d81f12016-07-08 15:42:16 -0700471 return 0;
David Benjamind246b812016-07-08 15:07:02 -0700472 }
473}
474
David Benjamina2d81f12016-07-08 15:42:16 -0700475static int ssl_sign_rsa_pkcs1(SSL *ssl, uint8_t *out, size_t *out_len,
476 size_t max_out, const EVP_MD *md,
477 const uint8_t *in, size_t in_len) {
478 EVP_MD_CTX ctx;
479 EVP_MD_CTX_init(&ctx);
480 *out_len = max_out;
481 int ret = EVP_DigestSignInit(&ctx, NULL, md, NULL, ssl->cert->privatekey) &&
482 EVP_DigestSignUpdate(&ctx, in, in_len) &&
483 EVP_DigestSignFinal(&ctx, out, out_len);
484 EVP_MD_CTX_cleanup(&ctx);
485 return ret;
486}
487
488static int ssl_verify_rsa_pkcs1(SSL *ssl, const uint8_t *signature,
489 size_t signature_len, const EVP_MD *md,
490 EVP_PKEY *pkey, const uint8_t *in,
491 size_t in_len) {
David Benjamin887c3002016-07-08 16:15:32 -0700492 if (pkey->type != EVP_PKEY_RSA) {
493 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
494 return 0;
495 }
496
David Benjamina2d81f12016-07-08 15:42:16 -0700497 EVP_MD_CTX md_ctx;
498 EVP_MD_CTX_init(&md_ctx);
499 int ret = EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) &&
500 EVP_DigestVerifyUpdate(&md_ctx, in, in_len) &&
501 EVP_DigestVerifyFinal(&md_ctx, signature, signature_len);
502 EVP_MD_CTX_cleanup(&md_ctx);
503 return ret;
504}
505
David Benjamin1fb125c2016-07-08 18:52:12 -0700506static int is_ecdsa(int *out_curve, const EVP_MD **out_md, uint16_t sigalg) {
David Benjamina2d81f12016-07-08 15:42:16 -0700507 switch (sigalg) {
508 case SSL_SIGN_ECDSA_SHA1:
David Benjamin1fb125c2016-07-08 18:52:12 -0700509 *out_curve = NID_undef;
David Benjamina2d81f12016-07-08 15:42:16 -0700510 *out_md = EVP_sha1();
511 return 1;
512 case SSL_SIGN_ECDSA_SECP256R1_SHA256:
David Benjamin1fb125c2016-07-08 18:52:12 -0700513 *out_curve = NID_X9_62_prime256v1;
David Benjamina2d81f12016-07-08 15:42:16 -0700514 *out_md = EVP_sha256();
515 return 1;
516 case SSL_SIGN_ECDSA_SECP384R1_SHA384:
David Benjamin1fb125c2016-07-08 18:52:12 -0700517 *out_curve = NID_secp384r1;
David Benjamina2d81f12016-07-08 15:42:16 -0700518 *out_md = EVP_sha384();
519 return 1;
520 case SSL_SIGN_ECDSA_SECP521R1_SHA512:
David Benjamin1fb125c2016-07-08 18:52:12 -0700521 *out_curve = NID_secp521r1;
David Benjamina2d81f12016-07-08 15:42:16 -0700522 *out_md = EVP_sha512();
523 return 1;
524 default:
525 return 0;
526 }
527}
528
529static int ssl_sign_ecdsa(SSL *ssl, uint8_t *out, size_t *out_len,
David Benjamin1fb125c2016-07-08 18:52:12 -0700530 size_t max_out, int curve, const EVP_MD *md,
531 const uint8_t *in, size_t in_len) {
532 EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ssl->cert->privatekey);
533 if (ec_key == NULL) {
534 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
535 return 0;
536 }
537
538 /* In TLS 1.3, the curve is also specified by the signature algorithm. */
539 if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
540 (curve == NID_undef ||
541 EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) != curve)) {
542 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
543 return 0;
544 }
545
David Benjamina2d81f12016-07-08 15:42:16 -0700546 EVP_MD_CTX ctx;
547 EVP_MD_CTX_init(&ctx);
548 *out_len = max_out;
549 int ret = EVP_DigestSignInit(&ctx, NULL, md, NULL, ssl->cert->privatekey) &&
550 EVP_DigestSignUpdate(&ctx, in, in_len) &&
551 EVP_DigestSignFinal(&ctx, out, out_len);
552 EVP_MD_CTX_cleanup(&ctx);
553 return ret;
554}
555
556static int ssl_verify_ecdsa(SSL *ssl, const uint8_t *signature,
David Benjamin1fb125c2016-07-08 18:52:12 -0700557 size_t signature_len, int curve, const EVP_MD *md,
David Benjamina2d81f12016-07-08 15:42:16 -0700558 EVP_PKEY *pkey, const uint8_t *in, size_t in_len) {
David Benjamin1fb125c2016-07-08 18:52:12 -0700559 EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
560 if (ec_key == NULL) {
561 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
562 return 0;
563 }
564
565 /* In TLS 1.3, the curve is also specified by the signature algorithm. */
566 if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
567 (curve == NID_undef ||
568 EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) != curve)) {
David Benjamin887c3002016-07-08 16:15:32 -0700569 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
570 return 0;
571 }
572
David Benjamina2d81f12016-07-08 15:42:16 -0700573 EVP_MD_CTX md_ctx;
574 EVP_MD_CTX_init(&md_ctx);
575 int ret = EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) &&
576 EVP_DigestVerifyUpdate(&md_ctx, in, in_len) &&
577 EVP_DigestVerifyFinal(&md_ctx, signature, signature_len);
578 EVP_MD_CTX_cleanup(&md_ctx);
579 return ret;
580}
581
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400582static int is_rsa_pss(const EVP_MD **out_md, uint16_t sigalg) {
583 switch (sigalg) {
584 case SSL_SIGN_RSA_PSS_SHA256:
585 *out_md = EVP_sha256();
586 return 1;
587 case SSL_SIGN_RSA_PSS_SHA384:
588 *out_md = EVP_sha384();
589 return 1;
590 case SSL_SIGN_RSA_PSS_SHA512:
591 *out_md = EVP_sha512();
592 return 1;
593 default:
594 return 0;
595 }
596}
597
598static int ssl_sign_rsa_pss(SSL *ssl, uint8_t *out, size_t *out_len,
599 size_t max_out, const EVP_MD *md,
600 const uint8_t *in, size_t in_len) {
601 EVP_MD_CTX ctx;
602 EVP_MD_CTX_init(&ctx);
603 *out_len = max_out;
604 EVP_PKEY_CTX *pctx;
605 int ret =
606 EVP_DigestSignInit(&ctx, &pctx, md, NULL, ssl->cert->privatekey) &&
607 EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) &&
608 EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */) &&
609 EVP_DigestSignUpdate(&ctx, in, in_len) &&
610 EVP_DigestSignFinal(&ctx, out, out_len);
611 EVP_MD_CTX_cleanup(&ctx);
612 return ret;
613}
614
615static int ssl_verify_rsa_pss(SSL *ssl, const uint8_t *signature,
616 size_t signature_len, const EVP_MD *md,
617 EVP_PKEY *pkey, const uint8_t *in,
618 size_t in_len) {
619 if (pkey->type != EVP_PKEY_RSA) {
620 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
621 return 0;
622 }
623
624 EVP_MD_CTX md_ctx;
625 EVP_MD_CTX_init(&md_ctx);
626 EVP_PKEY_CTX *pctx;
627 int ret =
628 EVP_DigestVerifyInit(&md_ctx, &pctx, md, NULL, pkey) &&
629 EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) &&
630 EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */) &&
631 EVP_DigestVerifyUpdate(&md_ctx, in, in_len) &&
632 EVP_DigestVerifyFinal(&md_ctx, signature, signature_len);
633 EVP_MD_CTX_cleanup(&md_ctx);
634 return ret;
635}
636
David Benjaminb4d65fd2015-05-29 17:11:21 -0400637enum ssl_private_key_result_t ssl_private_key_sign(
Steven Valdezf0451ca2016-06-29 13:16:27 -0400638 SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
639 uint16_t signature_algorithm, const uint8_t *in, size_t in_len) {
David Benjaminb4d65fd2015-05-29 17:11:21 -0400640 if (ssl->cert->key_method != NULL) {
David Benjamind3440b42016-07-14 14:52:41 -0400641 if (ssl->cert->key_method->sign != NULL) {
642 return ssl->cert->key_method->sign(ssl, out, out_len, max_out,
643 signature_algorithm, in, in_len);
644 }
645
646 /* TODO(davidben): Remove support for |sign_digest|-only
647 * |SSL_PRIVATE_KEY_METHOD|s. */
David Benjamina2d81f12016-07-08 15:42:16 -0700648 const EVP_MD *md;
David Benjamin1fb125c2016-07-08 18:52:12 -0700649 int curve;
David Benjamina2d81f12016-07-08 15:42:16 -0700650 if (!is_rsa_pkcs1(&md, signature_algorithm) &&
David Benjamin1fb125c2016-07-08 18:52:12 -0700651 !is_ecdsa(&curve, &md, signature_algorithm)) {
David Benjamina2d81f12016-07-08 15:42:16 -0700652 OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
653 return ssl_private_key_failure;
654 }
655
656 uint8_t hash[EVP_MAX_MD_SIZE];
657 unsigned hash_len;
658 if (!EVP_Digest(in, in_len, hash, &hash_len, md, NULL)) {
659 return ssl_private_key_failure;
660 }
661
David Benjamind3440b42016-07-14 14:52:41 -0400662 return ssl->cert->key_method->sign_digest(ssl, out, out_len, max_out, md,
663 hash, hash_len);
David Benjaminb4d65fd2015-05-29 17:11:21 -0400664 }
665
David Benjamina2d81f12016-07-08 15:42:16 -0700666 const EVP_MD *md;
Steven Valdez54ed58e2016-08-18 14:03:49 -0400667 if (is_rsa_pkcs1(&md, signature_algorithm) &&
668 ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
David Benjamina2d81f12016-07-08 15:42:16 -0700669 return ssl_sign_rsa_pkcs1(ssl, out, out_len, max_out, md, in, in_len)
670 ? ssl_private_key_success
671 : ssl_private_key_failure;
672 }
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400673
David Benjamin1fb125c2016-07-08 18:52:12 -0700674 int curve;
675 if (is_ecdsa(&curve, &md, signature_algorithm)) {
676 return ssl_sign_ecdsa(ssl, out, out_len, max_out, curve, md, in, in_len)
David Benjamina2d81f12016-07-08 15:42:16 -0700677 ? ssl_private_key_success
678 : ssl_private_key_failure;
David Benjaminb4d65fd2015-05-29 17:11:21 -0400679 }
680
David Benjamin0e950152016-08-13 21:08:56 -0400681 if (is_rsa_pss(&md, signature_algorithm)) {
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400682 return ssl_sign_rsa_pss(ssl, out, out_len, max_out, md, in, in_len)
683 ? ssl_private_key_success
684 : ssl_private_key_failure;
685 }
686
David Benjamina2d81f12016-07-08 15:42:16 -0700687 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
688 return ssl_private_key_failure;
David Benjaminb4d65fd2015-05-29 17:11:21 -0400689}
690
Steven Valdez2b8415e2016-06-30 13:27:23 -0400691int ssl_public_key_verify(SSL *ssl, const uint8_t *signature,
692 size_t signature_len, uint16_t signature_algorithm,
693 EVP_PKEY *pkey, const uint8_t *in, size_t in_len) {
David Benjamina2d81f12016-07-08 15:42:16 -0700694 const EVP_MD *md;
Steven Valdez54ed58e2016-08-18 14:03:49 -0400695 if (is_rsa_pkcs1(&md, signature_algorithm) &&
696 ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
David Benjamina2d81f12016-07-08 15:42:16 -0700697 return ssl_verify_rsa_pkcs1(ssl, signature, signature_len, md, pkey, in,
698 in_len);
699 }
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400700
David Benjamin1fb125c2016-07-08 18:52:12 -0700701 int curve;
702 if (is_ecdsa(&curve, &md, signature_algorithm)) {
703 return ssl_verify_ecdsa(ssl, signature, signature_len, curve, md, pkey, in,
David Benjamina2d81f12016-07-08 15:42:16 -0700704 in_len);
Steven Valdez2b8415e2016-06-30 13:27:23 -0400705 }
706
David Benjamin0e950152016-08-13 21:08:56 -0400707 if (is_rsa_pss(&md, signature_algorithm)) {
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400708 return ssl_verify_rsa_pss(ssl, signature, signature_len, md, pkey, in,
709 in_len);
710 }
711
David Benjamina2d81f12016-07-08 15:42:16 -0700712 OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
713 return 0;
Steven Valdez2b8415e2016-06-30 13:27:23 -0400714}
715
nagendra modadugu3398dbf2015-08-07 14:07:52 -0700716enum ssl_private_key_result_t ssl_private_key_decrypt(
717 SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
718 const uint8_t *in, size_t in_len) {
719 if (ssl->cert->key_method != NULL) {
720 return ssl->cert->key_method->decrypt(ssl, out, out_len, max_out, in,
721 in_len);
722 }
723
David Benjamin758d1272015-11-20 17:47:25 -0500724 RSA *rsa = EVP_PKEY_get0_RSA(ssl->cert->privatekey);
725 if (rsa == NULL) {
nagendra modadugu3398dbf2015-08-07 14:07:52 -0700726 /* Decrypt operations are only supported for RSA keys. */
727 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
728 return ssl_private_key_failure;
729 }
730
nagendra modadugu3398dbf2015-08-07 14:07:52 -0700731 /* Decrypt with no padding. PKCS#1 padding will be removed as part
732 * of the timing-sensitive code by the caller. */
David Benjamin758d1272015-11-20 17:47:25 -0500733 if (!RSA_decrypt(rsa, out_len, out, max_out, in, in_len, RSA_NO_PADDING)) {
734 return ssl_private_key_failure;
nagendra modadugu3398dbf2015-08-07 14:07:52 -0700735 }
David Benjamin758d1272015-11-20 17:47:25 -0500736 return ssl_private_key_success;
nagendra modadugu3398dbf2015-08-07 14:07:52 -0700737}
738
David Benjamind3440b42016-07-14 14:52:41 -0400739enum ssl_private_key_result_t ssl_private_key_complete(SSL *ssl, uint8_t *out,
740 size_t *out_len,
741 size_t max_out) {
nagendra modadugu3398dbf2015-08-07 14:07:52 -0700742 /* Only custom keys may be asynchronous. */
David Benjamind3440b42016-07-14 14:52:41 -0400743 return ssl->cert->key_method->complete(ssl, out, out_len, max_out);
nagendra modadugu3398dbf2015-08-07 14:07:52 -0700744}
David Benjamin1fb125c2016-07-08 18:52:12 -0700745
746int ssl_private_key_supports_signature_algorithm(SSL *ssl,
747 uint16_t signature_algorithm) {
748 const EVP_MD *md;
Steven Valdez54ed58e2016-08-18 14:03:49 -0400749 if (is_rsa_pkcs1(&md, signature_algorithm) &&
750 ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
David Benjamin0c0b7e12016-07-14 13:47:55 -0400751 return ssl_private_key_type(ssl) == NID_rsaEncryption;
David Benjamin1fb125c2016-07-08 18:52:12 -0700752 }
753
754 int curve;
755 if (is_ecdsa(&curve, &md, signature_algorithm)) {
David Benjamin0c0b7e12016-07-14 13:47:55 -0400756 int type = ssl_private_key_type(ssl);
757 if (!ssl_is_ecdsa_key_type(type)) {
David Benjamin1fb125c2016-07-08 18:52:12 -0700758 return 0;
759 }
760
David Benjamin0c0b7e12016-07-14 13:47:55 -0400761 /* Prior to TLS 1.3, ECDSA curves did not match the signature algorithm. */
762 if (ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
763 return 1;
David Benjamin1fb125c2016-07-08 18:52:12 -0700764 }
David Benjamin0c0b7e12016-07-14 13:47:55 -0400765
766 /* TODO(davidben): Remove support for EVP_PKEY_EC keys. */
767 return curve != NID_undef && (type == EVP_PKEY_EC || type == curve);
David Benjamin1fb125c2016-07-08 18:52:12 -0700768 }
769
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400770 if (is_rsa_pss(&md, signature_algorithm)) {
David Benjamin0e950152016-08-13 21:08:56 -0400771 if (ssl_private_key_type(ssl) != NID_rsaEncryption) {
David Benjamin7944a9f2016-07-12 22:27:01 -0400772 return 0;
773 }
774
775 /* Ensure the RSA key is large enough for the hash. RSASSA-PSS requires that
776 * emLen be at least hLen + sLen + 2. Both hLen and sLen are the size of the
777 * hash in TLS. Reasonable RSA key sizes are large enough for the largest
778 * defined RSASSA-PSS algorithm, but 1024-bit RSA is slightly too large for
779 * SHA-512. 1024-bit RSA is sometimes used for test credentials, so check
780 * the size to fall back to another algorithm. */
781 if (ssl_private_key_max_signature_len(ssl) < 2 * EVP_MD_size(md) + 2) {
782 return 0;
783 }
784
David Benjamind3440b42016-07-14 14:52:41 -0400785 /* RSA-PSS is only supported by message-based private keys. */
786 if (ssl->cert->key_method != NULL && ssl->cert->key_method->sign == NULL) {
787 return 0;
788 }
789
David Benjamin7944a9f2016-07-12 22:27:01 -0400790 return 1;
Steven Valdezeff1e8d2016-07-06 14:24:47 -0400791 }
792
David Benjamin1fb125c2016-07-08 18:52:12 -0700793 return 0;
794}