blob: fb6fdf60025558b5887ada4ccff3a8f40489e56c [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
Adam Langley95c29f32014-06-20 12:00:00 -070059#include <openssl/err.h>
60#include <openssl/evp.h>
61#include <openssl/mem.h>
Adam Langley95c29f32014-06-20 12:00:00 -070062#include <openssl/x509.h>
63
David Benjamin2ee94aa2015-04-07 22:38:30 -040064#include "internal.h"
Adam Langley95c29f32014-06-20 12:00:00 -070065
David Benjamin443a1f62015-09-04 15:05:05 -040066
Adam Langley95c29f32014-06-20 12:00:00 -070067static int ssl_set_cert(CERT *c, X509 *x509);
68static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey);
Adam Langley95c29f32014-06-20 12:00:00 -070069
David Benjamind1d80782015-07-05 11:54:09 -040070static int is_key_type_supported(int key_type) {
71 return key_type == EVP_PKEY_RSA || key_type == EVP_PKEY_EC;
72}
73
Adam Langleyfcf25832014-12-18 17:42:32 -080074int SSL_use_certificate(SSL *ssl, X509 *x) {
75 if (x == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -040076 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -080077 return 0;
78 }
Adam Langleyfcf25832014-12-18 17:42:32 -080079 return ssl_set_cert(ssl->cert, x);
80}
Adam Langley95c29f32014-06-20 12:00:00 -070081
Adam Langleyfcf25832014-12-18 17:42:32 -080082int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *d, int len) {
83 X509 *x;
84 int ret;
85
86 x = d2i_X509(NULL, &d, (long)len);
87 if (x == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -040088 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -080089 return 0;
90 }
91
92 ret = SSL_use_certificate(ssl, x);
93 X509_free(x);
94 return ret;
95}
96
97int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
98 EVP_PKEY *pkey;
99 int ret;
100
101 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400102 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800103 return 0;
104 }
105
Adam Langleyfcf25832014-12-18 17:42:32 -0800106 pkey = EVP_PKEY_new();
107 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400108 OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800109 return 0;
110 }
111
112 RSA_up_ref(rsa);
113 EVP_PKEY_assign_RSA(pkey, rsa);
114
115 ret = ssl_set_pkey(ssl->cert, pkey);
116 EVP_PKEY_free(pkey);
117
118 return ret;
119}
120
121static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) {
David Benjamind1d80782015-07-05 11:54:09 -0400122 if (!is_key_type_supported(pkey->type)) {
David Benjamin3570d732015-06-29 00:28:17 -0400123 OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
Adam Langleyfcf25832014-12-18 17:42:32 -0800124 return 0;
125 }
126
David Benjamind1d80782015-07-05 11:54:09 -0400127 if (c->x509 != NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800128 /* Sanity-check that the private key and the certificate match, unless the
129 * key is opaque (in case of, say, a smartcard). */
130 if (!EVP_PKEY_is_opaque(pkey) &&
David Benjamind1d80782015-07-05 11:54:09 -0400131 !X509_check_private_key(c->x509, pkey)) {
132 X509_free(c->x509);
133 c->x509 = NULL;
Adam Langleyfcf25832014-12-18 17:42:32 -0800134 return 0;
135 }
136 }
137
David Benjamind1d80782015-07-05 11:54:09 -0400138 EVP_PKEY_free(c->privatekey);
139 c->privatekey = EVP_PKEY_up_ref(pkey);
Adam Langleyfcf25832014-12-18 17:42:32 -0800140
141 return 1;
142}
143
David Benjamin74f71102015-06-27 14:56:25 -0400144int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
145 RSA *rsa = RSA_private_key_from_bytes(der, der_len);
Adam Langleyfcf25832014-12-18 17:42:32 -0800146 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400147 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800148 return 0;
149 }
150
David Benjamin74f71102015-06-27 14:56:25 -0400151 int ret = SSL_use_RSAPrivateKey(ssl, rsa);
Adam Langleyfcf25832014-12-18 17:42:32 -0800152 RSA_free(rsa);
153 return ret;
154}
155
156int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) {
157 int ret;
158
159 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400160 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800161 return 0;
162 }
163
Adam Langleyfcf25832014-12-18 17:42:32 -0800164 ret = ssl_set_pkey(ssl->cert, pkey);
165 return ret;
166}
167
Adam Langleyfcf25832014-12-18 17:42:32 -0800168int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *d, long len) {
169 int ret;
170 const uint8_t *p;
171 EVP_PKEY *pkey;
172
173 p = d;
174 pkey = d2i_PrivateKey(type, NULL, &p, (long)len);
175 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400176 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800177 return 0;
178 }
179
180 ret = SSL_use_PrivateKey(ssl, pkey);
181 EVP_PKEY_free(pkey);
182 return ret;
183}
184
185int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) {
186 if (x == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400187 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800188 return 0;
189 }
Adam Langleyfcf25832014-12-18 17:42:32 -0800190
191 return ssl_set_cert(ctx->cert, x);
192}
193
194static int ssl_set_cert(CERT *c, X509 *x) {
David Benjamind1d80782015-07-05 11:54:09 -0400195 EVP_PKEY *pkey = X509_get_pubkey(x);
Adam Langleyfcf25832014-12-18 17:42:32 -0800196 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400197 OPENSSL_PUT_ERROR(SSL, SSL_R_X509_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800198 return 0;
199 }
200
David Benjamind1d80782015-07-05 11:54:09 -0400201 if (!is_key_type_supported(pkey->type)) {
David Benjamin3570d732015-06-29 00:28:17 -0400202 OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
Adam Langleyfcf25832014-12-18 17:42:32 -0800203 EVP_PKEY_free(pkey);
204 return 0;
205 }
206
David Benjamind1d80782015-07-05 11:54:09 -0400207 if (c->privatekey != NULL) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800208 /* Sanity-check that the private key and the certificate match, unless the
209 * key is opaque (in case of, say, a smartcard). */
David Benjamind1d80782015-07-05 11:54:09 -0400210 if (!EVP_PKEY_is_opaque(c->privatekey) &&
211 !X509_check_private_key(x, c->privatekey)) {
Adam Langleyfcf25832014-12-18 17:42:32 -0800212 /* don't fail for a cert/key mismatch, just free current private key
213 * (when switching to a different cert & key, first this function should
214 * be used, then ssl_set_pkey */
David Benjamind1d80782015-07-05 11:54:09 -0400215 EVP_PKEY_free(c->privatekey);
216 c->privatekey = NULL;
Adam Langleyfcf25832014-12-18 17:42:32 -0800217 /* clear error queue */
218 ERR_clear_error();
219 }
220 }
221
222 EVP_PKEY_free(pkey);
223
David Benjamind1d80782015-07-05 11:54:09 -0400224 X509_free(c->x509);
225 c->x509 = X509_up_ref(x);
Adam Langleyfcf25832014-12-18 17:42:32 -0800226
227 return 1;
228}
229
Adam Langleyfcf25832014-12-18 17:42:32 -0800230int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const uint8_t *d) {
231 X509 *x;
232 int ret;
233
234 x = d2i_X509(NULL, &d, (long)len);
235 if (x == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400236 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800237 return 0;
238 }
239
240 ret = SSL_CTX_use_certificate(ctx, x);
241 X509_free(x);
242 return ret;
243}
244
245int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) {
246 int ret;
247 EVP_PKEY *pkey;
248
249 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400250 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800251 return 0;
252 }
253
Adam Langleyfcf25832014-12-18 17:42:32 -0800254 pkey = EVP_PKEY_new();
255 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400256 OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800257 return 0;
258 }
259
260 RSA_up_ref(rsa);
261 EVP_PKEY_assign_RSA(pkey, rsa);
262
263 ret = ssl_set_pkey(ctx->cert, pkey);
264 EVP_PKEY_free(pkey);
265 return ret;
266}
267
David Benjamin74f71102015-06-27 14:56:25 -0400268int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *der,
269 size_t der_len) {
270 RSA *rsa = RSA_private_key_from_bytes(der, der_len);
Adam Langleyfcf25832014-12-18 17:42:32 -0800271 if (rsa == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400272 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800273 return 0;
274 }
275
David Benjamin74f71102015-06-27 14:56:25 -0400276 int ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
Adam Langleyfcf25832014-12-18 17:42:32 -0800277 RSA_free(rsa);
278 return ret;
279}
280
281int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) {
282 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400283 OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyfcf25832014-12-18 17:42:32 -0800284 return 0;
285 }
286
Adam Langleyfcf25832014-12-18 17:42:32 -0800287 return ssl_set_pkey(ctx->cert, pkey);
288}
289
Adam Langleyfcf25832014-12-18 17:42:32 -0800290int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *d,
291 long len) {
292 int ret;
293 const uint8_t *p;
294 EVP_PKEY *pkey;
295
296 p = d;
297 pkey = d2i_PrivateKey(type, NULL, &p, (long)len);
298 if (pkey == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400299 OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
Adam Langleyfcf25832014-12-18 17:42:32 -0800300 return 0;
301 }
302
303 ret = SSL_CTX_use_PrivateKey(ctx, pkey);
304 EVP_PKEY_free(pkey);
305 return ret;
306}
307
David Benjaminb4d65fd2015-05-29 17:11:21 -0400308void SSL_set_private_key_method(SSL *ssl,
309 const SSL_PRIVATE_KEY_METHOD *key_method) {
310 ssl->cert->key_method = key_method;
311}
312
nagendra modadugu601448a2015-07-24 09:31:31 -0700313int ssl_has_private_key(SSL *ssl) {
314 return ssl->cert->privatekey != NULL || ssl->cert->key_method != NULL;
315}
316
David Benjamind1d80782015-07-05 11:54:09 -0400317int ssl_private_key_type(SSL *ssl) {
David Benjaminb4d65fd2015-05-29 17:11:21 -0400318 if (ssl->cert->key_method != NULL) {
319 return ssl->cert->key_method->type(ssl);
320 }
David Benjamind1d80782015-07-05 11:54:09 -0400321 return EVP_PKEY_id(ssl->cert->privatekey);
David Benjaminb4d65fd2015-05-29 17:11:21 -0400322}
323
David Benjamind1d80782015-07-05 11:54:09 -0400324int ssl_private_key_supports_digest(SSL *ssl, const EVP_MD *md) {
David Benjaminb4d65fd2015-05-29 17:11:21 -0400325 if (ssl->cert->key_method != NULL) {
326 return ssl->cert->key_method->supports_digest(ssl, md);
327 }
David Benjamind1d80782015-07-05 11:54:09 -0400328 return EVP_PKEY_supports_digest(ssl->cert->privatekey, md);
David Benjaminb4d65fd2015-05-29 17:11:21 -0400329}
330
David Benjamind1d80782015-07-05 11:54:09 -0400331size_t ssl_private_key_max_signature_len(SSL *ssl) {
David Benjaminb4d65fd2015-05-29 17:11:21 -0400332 if (ssl->cert->key_method != NULL) {
333 return ssl->cert->key_method->max_signature_len(ssl);
334 }
David Benjamind1d80782015-07-05 11:54:09 -0400335 return EVP_PKEY_size(ssl->cert->privatekey);
David Benjaminb4d65fd2015-05-29 17:11:21 -0400336}
337
338enum ssl_private_key_result_t ssl_private_key_sign(
David Benjamind1d80782015-07-05 11:54:09 -0400339 SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, const EVP_MD *md,
340 const uint8_t *in, size_t in_len) {
David Benjaminb4d65fd2015-05-29 17:11:21 -0400341 if (ssl->cert->key_method != NULL) {
342 return ssl->cert->key_method->sign(ssl, out, out_len, max_out, md, in,
343 in_len);
344 }
345
346 enum ssl_private_key_result_t ret = ssl_private_key_failure;
David Benjamind1d80782015-07-05 11:54:09 -0400347 EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
David Benjaminb4d65fd2015-05-29 17:11:21 -0400348 if (ctx == NULL) {
349 goto end;
350 }
351
352 size_t len = max_out;
353 if (!EVP_PKEY_sign_init(ctx) ||
354 !EVP_PKEY_CTX_set_signature_md(ctx, md) ||
355 !EVP_PKEY_sign(ctx, out, &len, in, in_len)) {
356 goto end;
357 }
358 *out_len = len;
359 ret = ssl_private_key_success;
360
361end:
362 EVP_PKEY_CTX_free(ctx);
363 return ret;
364}
365
366enum ssl_private_key_result_t ssl_private_key_sign_complete(
367 SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) {
368 /* Only custom keys may be asynchronous. */
369 return ssl->cert->key_method->sign_complete(ssl, out, out_len, max_out);
370}