blob: da69f8bff7bc250b3c2c9a8bebbd5cf69bafbd38 [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
57#include <stdio.h>
58
59#include <openssl/bio.h>
60#include <openssl/err.h>
61#include <openssl/evp.h>
62#include <openssl/mem.h>
63#include <openssl/obj.h>
64#include <openssl/pem.h>
65#include <openssl/x509.h>
66
David Benjamin2ee94aa2015-04-07 22:38:30 -040067#include "internal.h"
Adam Langley95c29f32014-06-20 12:00:00 -070068
69static int ssl_set_cert(CERT *c, X509 *x509);
70static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey);
Adam Langley95c29f32014-06-20 12:00:00 -070071
David Benjamind1d80782015-07-05 11:54:09 -040072static int is_key_type_supported(int key_type) {
73 return key_type == EVP_PKEY_RSA || key_type == EVP_PKEY_EC;
74}
75
Adam Langleyfcf25832014-12-18 17:42:32 -080076int SSL_use_certificate(SSL *ssl, X509 *x) {
77 if (x == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -040078 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -080079 return 0;
80 }
Adam Langleyfcf25832014-12-18 17:42:32 -080081 return ssl_set_cert(ssl->cert, x);
82}
Adam Langley95c29f32014-06-20 12:00:00 -070083
Adam Langleyfcf25832014-12-18 17:42:32 -080084int SSL_use_certificate_file(SSL *ssl, const char *file, int type) {
85 int reason_code;
86 BIO *in;
87 int ret = 0;
88 X509 *x = NULL;
Adam Langley95c29f32014-06-20 12:00:00 -070089
Adam Langleyfcf25832014-12-18 17:42:32 -080090 in = BIO_new(BIO_s_file());
91 if (in == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -040092 OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -080093 goto end;
94 }
Adam Langley95c29f32014-06-20 12:00:00 -070095
Adam Langleyfcf25832014-12-18 17:42:32 -080096 if (BIO_read_filename(in, file) <= 0) {
David Benjamin3570d732015-06-29 00:28:17 -040097 OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -080098 goto end;
99 }
Adam Langley95c29f32014-06-20 12:00:00 -0700100
Adam Langleyfcf25832014-12-18 17:42:32 -0800101 if (type == SSL_FILETYPE_ASN1) {
102 reason_code = ERR_R_ASN1_LIB;
103 x = d2i_X509_bio(in, NULL);
104 } else if (type == SSL_FILETYPE_PEM) {
105 reason_code = ERR_R_PEM_LIB;
106 x = PEM_read_bio_X509(in, NULL, ssl->ctx->default_passwd_callback,
107 ssl->ctx->default_passwd_callback_userdata);
108 } else {
David Benjamin3570d732015-06-29 00:28:17 -0400109 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
Adam Langleyfcf25832014-12-18 17:42:32 -0800110 goto end;
111 }
Adam Langley95c29f32014-06-20 12:00:00 -0700112
Adam Langleyfcf25832014-12-18 17:42:32 -0800113 if (x == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400114 OPENSSL_PUT_ERROR(SSL, reason_code);
Adam Langleyfcf25832014-12-18 17:42:32 -0800115 goto end;
116 }
Adam Langley95c29f32014-06-20 12:00:00 -0700117
Adam Langleyfcf25832014-12-18 17:42:32 -0800118 ret = SSL_use_certificate(ssl, x);
Adam Langley95c29f32014-06-20 12:00:00 -0700119
120end:
David Benjamin2755a3e2015-04-22 16:17:58 -0400121 X509_free(x);
122 BIO_free(in);
Adam Langleyfcf25832014-12-18 17:42:32 -0800123
124 return ret;
125}
126
127int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *d, int len) {
128 X509 *x;
129 int ret;
130
131 x = d2i_X509(NULL, &d, (long)len);
132 if (x == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400133 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800134 return 0;
135 }
136
137 ret = SSL_use_certificate(ssl, x);
138 X509_free(x);
139 return ret;
140}
141
142int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
143 EVP_PKEY *pkey;
144 int ret;
145
146 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400147 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800148 return 0;
149 }
150
Adam Langleyfcf25832014-12-18 17:42:32 -0800151 pkey = EVP_PKEY_new();
152 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400153 OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800154 return 0;
155 }
156
157 RSA_up_ref(rsa);
158 EVP_PKEY_assign_RSA(pkey, rsa);
159
160 ret = ssl_set_pkey(ssl->cert, pkey);
161 EVP_PKEY_free(pkey);
162
163 return ret;
164}
165
166static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) {
David Benjamind1d80782015-07-05 11:54:09 -0400167 if (!is_key_type_supported(pkey->type)) {
David Benjamin3570d732015-06-29 00:28:17 -0400168 OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
Adam Langleyfcf25832014-12-18 17:42:32 -0800169 return 0;
170 }
171
David Benjamind1d80782015-07-05 11:54:09 -0400172 if (c->x509 != NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800173 /* Sanity-check that the private key and the certificate match, unless the
174 * key is opaque (in case of, say, a smartcard). */
175 if (!EVP_PKEY_is_opaque(pkey) &&
David Benjamind1d80782015-07-05 11:54:09 -0400176 !X509_check_private_key(c->x509, pkey)) {
177 X509_free(c->x509);
178 c->x509 = NULL;
Adam Langleyfcf25832014-12-18 17:42:32 -0800179 return 0;
180 }
181 }
182
David Benjamind1d80782015-07-05 11:54:09 -0400183 EVP_PKEY_free(c->privatekey);
184 c->privatekey = EVP_PKEY_up_ref(pkey);
Adam Langleyfcf25832014-12-18 17:42:32 -0800185
186 return 1;
187}
188
189int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) {
190 int reason_code, ret = 0;
191 BIO *in;
192 RSA *rsa = NULL;
193
194 in = BIO_new(BIO_s_file());
195 if (in == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400196 OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800197 goto end;
198 }
199
200 if (BIO_read_filename(in, file) <= 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400201 OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800202 goto end;
203 }
204
205 if (type == SSL_FILETYPE_ASN1) {
206 reason_code = ERR_R_ASN1_LIB;
207 rsa = d2i_RSAPrivateKey_bio(in, NULL);
208 } else if (type == SSL_FILETYPE_PEM) {
209 reason_code = ERR_R_PEM_LIB;
210 rsa =
211 PEM_read_bio_RSAPrivateKey(in, NULL, ssl->ctx->default_passwd_callback,
212 ssl->ctx->default_passwd_callback_userdata);
213 } else {
David Benjamin3570d732015-06-29 00:28:17 -0400214 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
Adam Langleyfcf25832014-12-18 17:42:32 -0800215 goto end;
216 }
217
218 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400219 OPENSSL_PUT_ERROR(SSL, reason_code);
Adam Langleyfcf25832014-12-18 17:42:32 -0800220 goto end;
221 }
222 ret = SSL_use_RSAPrivateKey(ssl, rsa);
223 RSA_free(rsa);
224
225end:
David Benjamin2755a3e2015-04-22 16:17:58 -0400226 BIO_free(in);
Adam Langleyfcf25832014-12-18 17:42:32 -0800227 return ret;
228}
229
David Benjamin74f71102015-06-27 14:56:25 -0400230int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
231 RSA *rsa = RSA_private_key_from_bytes(der, der_len);
Adam Langleyfcf25832014-12-18 17:42:32 -0800232 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400233 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800234 return 0;
235 }
236
David Benjamin74f71102015-06-27 14:56:25 -0400237 int ret = SSL_use_RSAPrivateKey(ssl, rsa);
Adam Langleyfcf25832014-12-18 17:42:32 -0800238 RSA_free(rsa);
239 return ret;
240}
241
242int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) {
243 int ret;
244
245 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400246 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800247 return 0;
248 }
249
Adam Langleyfcf25832014-12-18 17:42:32 -0800250 ret = ssl_set_pkey(ssl->cert, pkey);
251 return ret;
252}
253
254int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) {
255 int reason_code, ret = 0;
256 BIO *in;
257 EVP_PKEY *pkey = NULL;
258
259 in = BIO_new(BIO_s_file());
260 if (in == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400261 OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800262 goto end;
263 }
264
265 if (BIO_read_filename(in, file) <= 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400266 OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800267 goto end;
268 }
269
270 if (type == SSL_FILETYPE_PEM) {
271 reason_code = ERR_R_PEM_LIB;
272 pkey = PEM_read_bio_PrivateKey(in, NULL, ssl->ctx->default_passwd_callback,
273 ssl->ctx->default_passwd_callback_userdata);
274 } else if (type == SSL_FILETYPE_ASN1) {
275 reason_code = ERR_R_ASN1_LIB;
276 pkey = d2i_PrivateKey_bio(in, NULL);
277 } else {
David Benjamin3570d732015-06-29 00:28:17 -0400278 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
Adam Langleyfcf25832014-12-18 17:42:32 -0800279 goto end;
280 }
281
282 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400283 OPENSSL_PUT_ERROR(SSL, reason_code);
Adam Langleyfcf25832014-12-18 17:42:32 -0800284 goto end;
285 }
286 ret = SSL_use_PrivateKey(ssl, pkey);
287 EVP_PKEY_free(pkey);
288
289end:
David Benjamin2755a3e2015-04-22 16:17:58 -0400290 BIO_free(in);
Adam Langleyfcf25832014-12-18 17:42:32 -0800291 return ret;
292}
293
294int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *d, long len) {
295 int ret;
296 const uint8_t *p;
297 EVP_PKEY *pkey;
298
299 p = d;
300 pkey = d2i_PrivateKey(type, NULL, &p, (long)len);
301 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400302 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800303 return 0;
304 }
305
306 ret = SSL_use_PrivateKey(ssl, pkey);
307 EVP_PKEY_free(pkey);
308 return ret;
309}
310
311int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) {
312 if (x == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400313 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800314 return 0;
315 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800316
317 return ssl_set_cert(ctx->cert, x);
318}
319
320static int ssl_set_cert(CERT *c, X509 *x) {
David Benjamind1d80782015-07-05 11:54:09 -0400321 EVP_PKEY *pkey = X509_get_pubkey(x);
Adam Langleyfcf25832014-12-18 17:42:32 -0800322 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400323 OPENSSL_PUT_ERROR(SSL, SSL_R_X509_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800324 return 0;
325 }
326
David Benjamind1d80782015-07-05 11:54:09 -0400327 if (!is_key_type_supported(pkey->type)) {
David Benjamin3570d732015-06-29 00:28:17 -0400328 OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
Adam Langleyfcf25832014-12-18 17:42:32 -0800329 EVP_PKEY_free(pkey);
330 return 0;
331 }
332
David Benjamind1d80782015-07-05 11:54:09 -0400333 if (c->privatekey != NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800334 /* Sanity-check that the private key and the certificate match, unless the
335 * key is opaque (in case of, say, a smartcard). */
David Benjamind1d80782015-07-05 11:54:09 -0400336 if (!EVP_PKEY_is_opaque(c->privatekey) &&
337 !X509_check_private_key(x, c->privatekey)) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800338 /* don't fail for a cert/key mismatch, just free current private key
339 * (when switching to a different cert & key, first this function should
340 * be used, then ssl_set_pkey */
David Benjamind1d80782015-07-05 11:54:09 -0400341 EVP_PKEY_free(c->privatekey);
342 c->privatekey = NULL;
Adam Langleyfcf25832014-12-18 17:42:32 -0800343 /* clear error queue */
344 ERR_clear_error();
345 }
346 }
347
348 EVP_PKEY_free(pkey);
349
David Benjamind1d80782015-07-05 11:54:09 -0400350 X509_free(c->x509);
351 c->x509 = X509_up_ref(x);
Adam Langleyfcf25832014-12-18 17:42:32 -0800352
353 return 1;
354}
355
356int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) {
357 int reason_code;
358 BIO *in;
359 int ret = 0;
360 X509 *x = NULL;
361
362 in = BIO_new(BIO_s_file());
363 if (in == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400364 OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800365 goto end;
366 }
367
368 if (BIO_read_filename(in, file) <= 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400369 OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800370 goto end;
371 }
372
373 if (type == SSL_FILETYPE_ASN1) {
374 reason_code = ERR_R_ASN1_LIB;
375 x = d2i_X509_bio(in, NULL);
376 } else if (type == SSL_FILETYPE_PEM) {
377 reason_code = ERR_R_PEM_LIB;
378 x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
379 ctx->default_passwd_callback_userdata);
380 } else {
David Benjamin3570d732015-06-29 00:28:17 -0400381 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
Adam Langleyfcf25832014-12-18 17:42:32 -0800382 goto end;
383 }
384
385 if (x == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400386 OPENSSL_PUT_ERROR(SSL, reason_code);
Adam Langleyfcf25832014-12-18 17:42:32 -0800387 goto end;
388 }
389
390 ret = SSL_CTX_use_certificate(ctx, x);
391
392end:
David Benjamin2755a3e2015-04-22 16:17:58 -0400393 X509_free(x);
394 BIO_free(in);
Adam Langleyfcf25832014-12-18 17:42:32 -0800395 return ret;
396}
397
398int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const uint8_t *d) {
399 X509 *x;
400 int ret;
401
402 x = d2i_X509(NULL, &d, (long)len);
403 if (x == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400404 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800405 return 0;
406 }
407
408 ret = SSL_CTX_use_certificate(ctx, x);
409 X509_free(x);
410 return ret;
411}
412
413int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) {
414 int ret;
415 EVP_PKEY *pkey;
416
417 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400418 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800419 return 0;
420 }
421
Adam Langleyfcf25832014-12-18 17:42:32 -0800422 pkey = EVP_PKEY_new();
423 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400424 OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800425 return 0;
426 }
427
428 RSA_up_ref(rsa);
429 EVP_PKEY_assign_RSA(pkey, rsa);
430
431 ret = ssl_set_pkey(ctx->cert, pkey);
432 EVP_PKEY_free(pkey);
433 return ret;
434}
435
436int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) {
437 int reason_code, ret = 0;
438 BIO *in;
439 RSA *rsa = NULL;
440
441 in = BIO_new(BIO_s_file());
442 if (in == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400443 OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800444 goto end;
445 }
446
447 if (BIO_read_filename(in, file) <= 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400448 OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800449 goto end;
450 }
451
452 if (type == SSL_FILETYPE_ASN1) {
453 reason_code = ERR_R_ASN1_LIB;
454 rsa = d2i_RSAPrivateKey_bio(in, NULL);
455 } else if (type == SSL_FILETYPE_PEM) {
456 reason_code = ERR_R_PEM_LIB;
457 rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ctx->default_passwd_callback,
458 ctx->default_passwd_callback_userdata);
459 } else {
David Benjamin3570d732015-06-29 00:28:17 -0400460 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
Adam Langleyfcf25832014-12-18 17:42:32 -0800461 goto end;
462 }
463
464 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400465 OPENSSL_PUT_ERROR(SSL, reason_code);
Adam Langleyfcf25832014-12-18 17:42:32 -0800466 goto end;
467 }
468 ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
469 RSA_free(rsa);
470
471end:
David Benjamin2755a3e2015-04-22 16:17:58 -0400472 BIO_free(in);
Adam Langleyfcf25832014-12-18 17:42:32 -0800473 return ret;
474}
475
David Benjamin74f71102015-06-27 14:56:25 -0400476int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *der,
477 size_t der_len) {
478 RSA *rsa = RSA_private_key_from_bytes(der, der_len);
Adam Langleyfcf25832014-12-18 17:42:32 -0800479 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400480 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800481 return 0;
482 }
483
David Benjamin74f71102015-06-27 14:56:25 -0400484 int ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
Adam Langleyfcf25832014-12-18 17:42:32 -0800485 RSA_free(rsa);
486 return ret;
487}
488
489int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) {
490 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400491 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800492 return 0;
493 }
494
Adam Langleyfcf25832014-12-18 17:42:32 -0800495 return ssl_set_pkey(ctx->cert, pkey);
496}
497
498int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) {
499 int reason_code, ret = 0;
500 BIO *in;
501 EVP_PKEY *pkey = NULL;
502
503 in = BIO_new(BIO_s_file());
504 if (in == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400505 OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800506 goto end;
507 }
508
509 if (BIO_read_filename(in, file) <= 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400510 OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800511 goto end;
512 }
513
514 if (type == SSL_FILETYPE_PEM) {
515 reason_code = ERR_R_PEM_LIB;
516 pkey = PEM_read_bio_PrivateKey(in, NULL, ctx->default_passwd_callback,
517 ctx->default_passwd_callback_userdata);
518 } else if (type == SSL_FILETYPE_ASN1) {
519 reason_code = ERR_R_ASN1_LIB;
520 pkey = d2i_PrivateKey_bio(in, NULL);
521 } else {
David Benjamin3570d732015-06-29 00:28:17 -0400522 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SSL_FILETYPE);
Adam Langleyfcf25832014-12-18 17:42:32 -0800523 goto end;
524 }
525
526 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400527 OPENSSL_PUT_ERROR(SSL, reason_code);
Adam Langleyfcf25832014-12-18 17:42:32 -0800528 goto end;
529 }
530 ret = SSL_CTX_use_PrivateKey(ctx, pkey);
531 EVP_PKEY_free(pkey);
532
533end:
David Benjamin2755a3e2015-04-22 16:17:58 -0400534 BIO_free(in);
Adam Langleyfcf25832014-12-18 17:42:32 -0800535 return ret;
536}
537
538int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *d,
539 long len) {
540 int ret;
541 const uint8_t *p;
542 EVP_PKEY *pkey;
543
544 p = d;
545 pkey = d2i_PrivateKey(type, NULL, &p, (long)len);
546 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400547 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800548 return 0;
549 }
550
551 ret = SSL_CTX_use_PrivateKey(ctx, pkey);
552 EVP_PKEY_free(pkey);
553 return ret;
554}
555
556
557/* Read a file that contains our certificate in "PEM" format, possibly followed
558 * by a sequence of CA certificates that should be sent to the peer in the
559 * Certificate message. */
560int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) {
561 BIO *in;
562 int ret = 0;
563 X509 *x = NULL;
564
565 ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */
566
567 in = BIO_new(BIO_s_file());
568 if (in == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400569 OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800570 goto end;
571 }
572
573 if (BIO_read_filename(in, file) <= 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400574 OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800575 goto end;
576 }
577
578 x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback,
579 ctx->default_passwd_callback_userdata);
580 if (x == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400581 OPENSSL_PUT_ERROR(SSL, ERR_R_PEM_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800582 goto end;
583 }
584
585 ret = SSL_CTX_use_certificate(ctx, x);
586
587 if (ERR_peek_error() != 0) {
588 ret = 0; /* Key/certificate mismatch doesn't imply ret==0 ... */
589 }
590
591 if (ret) {
592 /* If we could set up our certificate, now proceed to the CA
593 * certificates. */
594 X509 *ca;
595 int r;
David Benjamin9362b6e2015-04-26 14:14:15 -0400596 uint32_t err;
Adam Langleyfcf25832014-12-18 17:42:32 -0800597
598 SSL_CTX_clear_chain_certs(ctx);
599
600 while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
601 ctx->default_passwd_callback_userdata)) !=
602 NULL) {
603 r = SSL_CTX_add0_chain_cert(ctx, ca);
604 if (!r) {
605 X509_free(ca);
606 ret = 0;
607 goto end;
608 }
609 /* Note that we must not free r if it was successfully added to the chain
610 * (while we must free the main certificate, since its reference count is
611 * increased by SSL_CTX_use_certificate). */
612 }
613
614 /* When the while loop ends, it's usually just EOF. */
615 err = ERR_peek_last_error();
616 if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
617 ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
618 ERR_clear_error();
619 } else {
620 ret = 0; /* some real error */
621 }
622 }
623
624end:
David Benjamin2755a3e2015-04-22 16:17:58 -0400625 X509_free(x);
626 BIO_free(in);
Adam Langleyfcf25832014-12-18 17:42:32 -0800627 return ret;
628}
David Benjaminb4d65fd2015-05-29 17:11:21 -0400629
630void SSL_set_private_key_method(SSL *ssl,
631 const SSL_PRIVATE_KEY_METHOD *key_method) {
632 ssl->cert->key_method = key_method;
633}
634
nagendra modadugu601448a2015-07-24 09:31:31 -0700635int ssl_has_private_key(SSL *ssl) {
636 return ssl->cert->privatekey != NULL || ssl->cert->key_method != NULL;
637}
638
David Benjamind1d80782015-07-05 11:54:09 -0400639int ssl_private_key_type(SSL *ssl) {
David Benjaminb4d65fd2015-05-29 17:11:21 -0400640 if (ssl->cert->key_method != NULL) {
641 return ssl->cert->key_method->type(ssl);
642 }
David Benjamind1d80782015-07-05 11:54:09 -0400643 return EVP_PKEY_id(ssl->cert->privatekey);
David Benjaminb4d65fd2015-05-29 17:11:21 -0400644}
645
David Benjamind1d80782015-07-05 11:54:09 -0400646int ssl_private_key_supports_digest(SSL *ssl, const EVP_MD *md) {
David Benjaminb4d65fd2015-05-29 17:11:21 -0400647 if (ssl->cert->key_method != NULL) {
648 return ssl->cert->key_method->supports_digest(ssl, md);
649 }
David Benjamind1d80782015-07-05 11:54:09 -0400650 return EVP_PKEY_supports_digest(ssl->cert->privatekey, md);
David Benjaminb4d65fd2015-05-29 17:11:21 -0400651}
652
David Benjamind1d80782015-07-05 11:54:09 -0400653size_t ssl_private_key_max_signature_len(SSL *ssl) {
David Benjaminb4d65fd2015-05-29 17:11:21 -0400654 if (ssl->cert->key_method != NULL) {
655 return ssl->cert->key_method->max_signature_len(ssl);
656 }
David Benjamind1d80782015-07-05 11:54:09 -0400657 return EVP_PKEY_size(ssl->cert->privatekey);
David Benjaminb4d65fd2015-05-29 17:11:21 -0400658}
659
660enum ssl_private_key_result_t ssl_private_key_sign(
David Benjamind1d80782015-07-05 11:54:09 -0400661 SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, const EVP_MD *md,
662 const uint8_t *in, size_t in_len) {
David Benjaminb4d65fd2015-05-29 17:11:21 -0400663 if (ssl->cert->key_method != NULL) {
664 return ssl->cert->key_method->sign(ssl, out, out_len, max_out, md, in,
665 in_len);
666 }
667
668 enum ssl_private_key_result_t ret = ssl_private_key_failure;
David Benjamind1d80782015-07-05 11:54:09 -0400669 EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
David Benjaminb4d65fd2015-05-29 17:11:21 -0400670 if (ctx == NULL) {
671 goto end;
672 }
673
674 size_t len = max_out;
675 if (!EVP_PKEY_sign_init(ctx) ||
676 !EVP_PKEY_CTX_set_signature_md(ctx, md) ||
677 !EVP_PKEY_sign(ctx, out, &len, in, in_len)) {
678 goto end;
679 }
680 *out_len = len;
681 ret = ssl_private_key_success;
682
683end:
684 EVP_PKEY_CTX_free(ctx);
685 return ret;
686}
687
688enum ssl_private_key_result_t ssl_private_key_sign_complete(
689 SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) {
690 /* Only custom keys may be asynchronous. */
691 return ssl->cert->key_method->sign_complete(ssl, out, out_len, max_out);
692}