]>
Commit | Line | Data |
---|---|---|
846e33c7 RS |
1 | /* |
2 | * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. | |
d02b48c6 | 3 | * |
846e33c7 RS |
4 | * Licensed under the OpenSSL license (the "License"). You may not use |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
d02b48c6 RE |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
7b63c0fa | 11 | #include "ssl_locl.h" |
ec577822 BM |
12 | #include <openssl/bio.h> |
13 | #include <openssl/objects.h> | |
14 | #include <openssl/evp.h> | |
15 | #include <openssl/x509.h> | |
16 | #include <openssl/pem.h> | |
d02b48c6 | 17 | |
d02b48c6 RE |
18 | static int ssl_set_cert(CERT *c, X509 *x509); |
19 | static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); | |
6b691a5c | 20 | int SSL_use_certificate(SSL *ssl, X509 *x) |
0f113f3e MC |
21 | { |
22 | int rv; | |
23 | if (x == NULL) { | |
24 | SSLerr(SSL_F_SSL_USE_CERTIFICATE, ERR_R_PASSED_NULL_PARAMETER); | |
25 | return (0); | |
26 | } | |
27 | rv = ssl_security_cert(ssl, NULL, x, 0, 1); | |
28 | if (rv != 1) { | |
29 | SSLerr(SSL_F_SSL_USE_CERTIFICATE, rv); | |
30 | return 0; | |
31 | } | |
32 | ||
0f113f3e MC |
33 | return (ssl_set_cert(ssl->cert, x)); |
34 | } | |
d02b48c6 | 35 | |
303c0028 | 36 | int SSL_use_certificate_file(SSL *ssl, const char *file, int type) |
0f113f3e MC |
37 | { |
38 | int j; | |
39 | BIO *in; | |
40 | int ret = 0; | |
41 | X509 *x = NULL; | |
42 | ||
9982cbbb | 43 | in = BIO_new(BIO_s_file()); |
0f113f3e MC |
44 | if (in == NULL) { |
45 | SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_BUF_LIB); | |
46 | goto end; | |
47 | } | |
48 | ||
49 | if (BIO_read_filename(in, file) <= 0) { | |
50 | SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_SYS_LIB); | |
51 | goto end; | |
52 | } | |
53 | if (type == SSL_FILETYPE_ASN1) { | |
54 | j = ERR_R_ASN1_LIB; | |
55 | x = d2i_X509_bio(in, NULL); | |
56 | } else if (type == SSL_FILETYPE_PEM) { | |
57 | j = ERR_R_PEM_LIB; | |
58 | x = PEM_read_bio_X509(in, NULL, ssl->ctx->default_passwd_callback, | |
59 | ssl->ctx->default_passwd_callback_userdata); | |
60 | } else { | |
61 | SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, SSL_R_BAD_SSL_FILETYPE); | |
62 | goto end; | |
63 | } | |
64 | ||
65 | if (x == NULL) { | |
66 | SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, j); | |
67 | goto end; | |
68 | } | |
69 | ||
70 | ret = SSL_use_certificate(ssl, x); | |
71 | end: | |
222561fe | 72 | X509_free(x); |
ca3a82c3 | 73 | BIO_free(in); |
0f113f3e MC |
74 | return (ret); |
75 | } | |
d02b48c6 | 76 | |
875a644a | 77 | int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len) |
0f113f3e MC |
78 | { |
79 | X509 *x; | |
80 | int ret; | |
81 | ||
82 | x = d2i_X509(NULL, &d, (long)len); | |
83 | if (x == NULL) { | |
84 | SSLerr(SSL_F_SSL_USE_CERTIFICATE_ASN1, ERR_R_ASN1_LIB); | |
85 | return (0); | |
86 | } | |
87 | ||
88 | ret = SSL_use_certificate(ssl, x); | |
89 | X509_free(x); | |
90 | return (ret); | |
91 | } | |
d02b48c6 | 92 | |
bc36ee62 | 93 | #ifndef OPENSSL_NO_RSA |
6b691a5c | 94 | int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) |
0f113f3e MC |
95 | { |
96 | EVP_PKEY *pkey; | |
97 | int ret; | |
98 | ||
99 | if (rsa == NULL) { | |
100 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); | |
101 | return (0); | |
102 | } | |
0f113f3e MC |
103 | if ((pkey = EVP_PKEY_new()) == NULL) { |
104 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY, ERR_R_EVP_LIB); | |
105 | return (0); | |
106 | } | |
107 | ||
108 | RSA_up_ref(rsa); | |
5f3d93e4 MC |
109 | if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) { |
110 | RSA_free(rsa); | |
563c1ec6 | 111 | EVP_PKEY_free(pkey); |
5f3d93e4 MC |
112 | return 0; |
113 | } | |
0f113f3e MC |
114 | |
115 | ret = ssl_set_pkey(ssl->cert, pkey); | |
116 | EVP_PKEY_free(pkey); | |
117 | return (ret); | |
118 | } | |
d02b48c6 RE |
119 | #endif |
120 | ||
6b691a5c | 121 | static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) |
0f113f3e MC |
122 | { |
123 | int i; | |
bc71f910 | 124 | i = ssl_cert_type(NULL, pkey); |
0f113f3e MC |
125 | if (i < 0) { |
126 | SSLerr(SSL_F_SSL_SET_PKEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE); | |
127 | return (0); | |
128 | } | |
129 | ||
130 | if (c->pkeys[i].x509 != NULL) { | |
131 | EVP_PKEY *pktmp; | |
8382fd3a | 132 | pktmp = X509_get0_pubkey(c->pkeys[i].x509); |
5f3d93e4 MC |
133 | if (pktmp == NULL) { |
134 | SSLerr(SSL_F_SSL_SET_PKEY, ERR_R_MALLOC_FAILURE); | |
5f3d93e4 MC |
135 | return 0; |
136 | } | |
137 | /* | |
138 | * The return code from EVP_PKEY_copy_parameters is deliberately | |
139 | * ignored. Some EVP_PKEY types cannot do this. | |
140 | */ | |
0f113f3e | 141 | EVP_PKEY_copy_parameters(pktmp, pkey); |
0f113f3e | 142 | ERR_clear_error(); |
dfeab068 | 143 | |
bc36ee62 | 144 | #ifndef OPENSSL_NO_RSA |
0f113f3e MC |
145 | /* |
146 | * Don't check the public/private key, this is mostly for smart | |
147 | * cards. | |
148 | */ | |
3aeb9348 | 149 | if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA |
a230b26e | 150 | && RSA_flags(EVP_PKEY_get0_RSA(pkey)) & RSA_METHOD_FLAG_NO_CHECK) ; |
0f113f3e | 151 | else |
58964a49 | 152 | #endif |
0f113f3e MC |
153 | if (!X509_check_private_key(c->pkeys[i].x509, pkey)) { |
154 | X509_free(c->pkeys[i].x509); | |
155 | c->pkeys[i].x509 = NULL; | |
156 | return 0; | |
157 | } | |
158 | } | |
159 | ||
25aaa98a | 160 | EVP_PKEY_free(c->pkeys[i].privatekey); |
3aeb9348 | 161 | EVP_PKEY_up_ref(pkey); |
0f113f3e MC |
162 | c->pkeys[i].privatekey = pkey; |
163 | c->key = &(c->pkeys[i]); | |
0f113f3e MC |
164 | return (1); |
165 | } | |
d02b48c6 | 166 | |
bc36ee62 | 167 | #ifndef OPENSSL_NO_RSA |
303c0028 | 168 | int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) |
0f113f3e MC |
169 | { |
170 | int j, ret = 0; | |
171 | BIO *in; | |
172 | RSA *rsa = NULL; | |
173 | ||
9982cbbb | 174 | in = BIO_new(BIO_s_file()); |
0f113f3e MC |
175 | if (in == NULL) { |
176 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, ERR_R_BUF_LIB); | |
177 | goto end; | |
178 | } | |
179 | ||
180 | if (BIO_read_filename(in, file) <= 0) { | |
181 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, ERR_R_SYS_LIB); | |
182 | goto end; | |
183 | } | |
184 | if (type == SSL_FILETYPE_ASN1) { | |
185 | j = ERR_R_ASN1_LIB; | |
186 | rsa = d2i_RSAPrivateKey_bio(in, NULL); | |
187 | } else if (type == SSL_FILETYPE_PEM) { | |
188 | j = ERR_R_PEM_LIB; | |
189 | rsa = PEM_read_bio_RSAPrivateKey(in, NULL, | |
190 | ssl->ctx->default_passwd_callback, | |
191 | ssl-> | |
192 | ctx->default_passwd_callback_userdata); | |
193 | } else { | |
194 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE); | |
195 | goto end; | |
196 | } | |
197 | if (rsa == NULL) { | |
198 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, j); | |
199 | goto end; | |
200 | } | |
201 | ret = SSL_use_RSAPrivateKey(ssl, rsa); | |
202 | RSA_free(rsa); | |
203 | end: | |
ca3a82c3 | 204 | BIO_free(in); |
0f113f3e MC |
205 | return (ret); |
206 | } | |
d02b48c6 | 207 | |
693b71fa | 208 | int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, long len) |
0f113f3e MC |
209 | { |
210 | int ret; | |
211 | const unsigned char *p; | |
212 | RSA *rsa; | |
213 | ||
214 | p = d; | |
215 | if ((rsa = d2i_RSAPrivateKey(NULL, &p, (long)len)) == NULL) { | |
216 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1, ERR_R_ASN1_LIB); | |
217 | return (0); | |
218 | } | |
219 | ||
220 | ret = SSL_use_RSAPrivateKey(ssl, rsa); | |
221 | RSA_free(rsa); | |
222 | return (ret); | |
223 | } | |
224 | #endif /* !OPENSSL_NO_RSA */ | |
d02b48c6 | 225 | |
6b691a5c | 226 | int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) |
0f113f3e MC |
227 | { |
228 | int ret; | |
229 | ||
230 | if (pkey == NULL) { | |
231 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); | |
232 | return (0); | |
233 | } | |
0f113f3e MC |
234 | ret = ssl_set_pkey(ssl->cert, pkey); |
235 | return (ret); | |
236 | } | |
d02b48c6 | 237 | |
303c0028 | 238 | int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) |
0f113f3e MC |
239 | { |
240 | int j, ret = 0; | |
241 | BIO *in; | |
242 | EVP_PKEY *pkey = NULL; | |
243 | ||
9982cbbb | 244 | in = BIO_new(BIO_s_file()); |
0f113f3e MC |
245 | if (in == NULL) { |
246 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB); | |
247 | goto end; | |
248 | } | |
249 | ||
250 | if (BIO_read_filename(in, file) <= 0) { | |
251 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, ERR_R_SYS_LIB); | |
252 | goto end; | |
253 | } | |
254 | if (type == SSL_FILETYPE_PEM) { | |
255 | j = ERR_R_PEM_LIB; | |
256 | pkey = PEM_read_bio_PrivateKey(in, NULL, | |
257 | ssl->ctx->default_passwd_callback, | |
258 | ssl-> | |
259 | ctx->default_passwd_callback_userdata); | |
260 | } else if (type == SSL_FILETYPE_ASN1) { | |
261 | j = ERR_R_ASN1_LIB; | |
262 | pkey = d2i_PrivateKey_bio(in, NULL); | |
263 | } else { | |
264 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE); | |
265 | goto end; | |
266 | } | |
267 | if (pkey == NULL) { | |
268 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, j); | |
269 | goto end; | |
270 | } | |
271 | ret = SSL_use_PrivateKey(ssl, pkey); | |
272 | EVP_PKEY_free(pkey); | |
273 | end: | |
ca3a82c3 | 274 | BIO_free(in); |
0f113f3e MC |
275 | return (ret); |
276 | } | |
d02b48c6 | 277 | |
0f113f3e MC |
278 | int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d, |
279 | long len) | |
280 | { | |
281 | int ret; | |
282 | const unsigned char *p; | |
283 | EVP_PKEY *pkey; | |
d02b48c6 | 284 | |
0f113f3e MC |
285 | p = d; |
286 | if ((pkey = d2i_PrivateKey(type, NULL, &p, (long)len)) == NULL) { | |
287 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY_ASN1, ERR_R_ASN1_LIB); | |
288 | return (0); | |
289 | } | |
d02b48c6 | 290 | |
0f113f3e MC |
291 | ret = SSL_use_PrivateKey(ssl, pkey); |
292 | EVP_PKEY_free(pkey); | |
293 | return (ret); | |
294 | } | |
d02b48c6 | 295 | |
6b691a5c | 296 | int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) |
0f113f3e MC |
297 | { |
298 | int rv; | |
299 | if (x == NULL) { | |
300 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE, ERR_R_PASSED_NULL_PARAMETER); | |
301 | return (0); | |
302 | } | |
303 | rv = ssl_security_cert(NULL, ctx, x, 0, 1); | |
304 | if (rv != 1) { | |
305 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE, rv); | |
306 | return 0; | |
307 | } | |
0f113f3e MC |
308 | return (ssl_set_cert(ctx->cert, x)); |
309 | } | |
d02b48c6 | 310 | |
6b691a5c | 311 | static int ssl_set_cert(CERT *c, X509 *x) |
0f113f3e MC |
312 | { |
313 | EVP_PKEY *pkey; | |
314 | int i; | |
315 | ||
8382fd3a | 316 | pkey = X509_get0_pubkey(x); |
0f113f3e MC |
317 | if (pkey == NULL) { |
318 | SSLerr(SSL_F_SSL_SET_CERT, SSL_R_X509_LIB); | |
319 | return (0); | |
320 | } | |
321 | ||
322 | i = ssl_cert_type(x, pkey); | |
323 | if (i < 0) { | |
324 | SSLerr(SSL_F_SSL_SET_CERT, SSL_R_UNKNOWN_CERTIFICATE_TYPE); | |
8382fd3a | 325 | return 0; |
0f113f3e | 326 | } |
760f317d | 327 | #ifndef OPENSSL_NO_EC |
1db3107a DSH |
328 | if (i == SSL_PKEY_ECC && !EC_KEY_can_sign(EVP_PKEY_get0_EC_KEY(pkey))) { |
329 | SSLerr(SSL_F_SSL_SET_CERT, SSL_R_ECC_CERT_NOT_FOR_SIGNING); | |
330 | return 0; | |
331 | } | |
760f317d | 332 | #endif |
0f113f3e | 333 | if (c->pkeys[i].privatekey != NULL) { |
5f3d93e4 MC |
334 | /* |
335 | * The return code from EVP_PKEY_copy_parameters is deliberately | |
336 | * ignored. Some EVP_PKEY types cannot do this. | |
337 | */ | |
0f113f3e MC |
338 | EVP_PKEY_copy_parameters(pkey, c->pkeys[i].privatekey); |
339 | ERR_clear_error(); | |
dfeab068 | 340 | |
bc36ee62 | 341 | #ifndef OPENSSL_NO_RSA |
0f113f3e MC |
342 | /* |
343 | * Don't check the public/private key, this is mostly for smart | |
344 | * cards. | |
345 | */ | |
3aeb9348 DSH |
346 | if (EVP_PKEY_id(c->pkeys[i].privatekey) == EVP_PKEY_RSA |
347 | && RSA_flags(EVP_PKEY_get0_RSA(c->pkeys[i].privatekey)) & | |
a230b26e | 348 | RSA_METHOD_FLAG_NO_CHECK) ; |
0f113f3e MC |
349 | else |
350 | #endif /* OPENSSL_NO_RSA */ | |
351 | if (!X509_check_private_key(x, c->pkeys[i].privatekey)) { | |
352 | /* | |
353 | * don't fail for a cert/key mismatch, just free current private | |
354 | * key (when switching to a different cert & key, first this | |
355 | * function should be used, then ssl_set_pkey | |
356 | */ | |
357 | EVP_PKEY_free(c->pkeys[i].privatekey); | |
358 | c->pkeys[i].privatekey = NULL; | |
359 | /* clear error queue */ | |
360 | ERR_clear_error(); | |
361 | } | |
362 | } | |
363 | ||
222561fe | 364 | X509_free(c->pkeys[i].x509); |
05f0fb9f | 365 | X509_up_ref(x); |
0f113f3e MC |
366 | c->pkeys[i].x509 = x; |
367 | c->key = &(c->pkeys[i]); | |
368 | ||
8382fd3a | 369 | return 1; |
0f113f3e | 370 | } |
d02b48c6 | 371 | |
303c0028 | 372 | int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) |
0f113f3e MC |
373 | { |
374 | int j; | |
375 | BIO *in; | |
376 | int ret = 0; | |
377 | X509 *x = NULL; | |
378 | ||
9982cbbb | 379 | in = BIO_new(BIO_s_file()); |
0f113f3e MC |
380 | if (in == NULL) { |
381 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_BUF_LIB); | |
382 | goto end; | |
383 | } | |
384 | ||
385 | if (BIO_read_filename(in, file) <= 0) { | |
386 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_SYS_LIB); | |
387 | goto end; | |
388 | } | |
389 | if (type == SSL_FILETYPE_ASN1) { | |
390 | j = ERR_R_ASN1_LIB; | |
391 | x = d2i_X509_bio(in, NULL); | |
392 | } else if (type == SSL_FILETYPE_PEM) { | |
393 | j = ERR_R_PEM_LIB; | |
394 | x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, | |
395 | ctx->default_passwd_callback_userdata); | |
396 | } else { | |
397 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, SSL_R_BAD_SSL_FILETYPE); | |
398 | goto end; | |
399 | } | |
400 | ||
401 | if (x == NULL) { | |
402 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, j); | |
403 | goto end; | |
404 | } | |
405 | ||
406 | ret = SSL_CTX_use_certificate(ctx, x); | |
407 | end: | |
222561fe | 408 | X509_free(x); |
ca3a82c3 | 409 | BIO_free(in); |
0f113f3e MC |
410 | return (ret); |
411 | } | |
d02b48c6 | 412 | |
a230b26e | 413 | int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d) |
0f113f3e MC |
414 | { |
415 | X509 *x; | |
416 | int ret; | |
d02b48c6 | 417 | |
0f113f3e MC |
418 | x = d2i_X509(NULL, &d, (long)len); |
419 | if (x == NULL) { | |
420 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1, ERR_R_ASN1_LIB); | |
421 | return (0); | |
422 | } | |
d02b48c6 | 423 | |
0f113f3e MC |
424 | ret = SSL_CTX_use_certificate(ctx, x); |
425 | X509_free(x); | |
426 | return (ret); | |
427 | } | |
d02b48c6 | 428 | |
bc36ee62 | 429 | #ifndef OPENSSL_NO_RSA |
6b691a5c | 430 | int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) |
0f113f3e MC |
431 | { |
432 | int ret; | |
433 | EVP_PKEY *pkey; | |
434 | ||
435 | if (rsa == NULL) { | |
436 | SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); | |
437 | return (0); | |
438 | } | |
0f113f3e MC |
439 | if ((pkey = EVP_PKEY_new()) == NULL) { |
440 | SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY, ERR_R_EVP_LIB); | |
441 | return (0); | |
442 | } | |
443 | ||
444 | RSA_up_ref(rsa); | |
5f3d93e4 MC |
445 | if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) { |
446 | RSA_free(rsa); | |
563c1ec6 | 447 | EVP_PKEY_free(pkey); |
5f3d93e4 MC |
448 | return 0; |
449 | } | |
0f113f3e MC |
450 | |
451 | ret = ssl_set_pkey(ctx->cert, pkey); | |
452 | EVP_PKEY_free(pkey); | |
453 | return (ret); | |
454 | } | |
455 | ||
303c0028 | 456 | int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) |
0f113f3e MC |
457 | { |
458 | int j, ret = 0; | |
459 | BIO *in; | |
460 | RSA *rsa = NULL; | |
461 | ||
9982cbbb | 462 | in = BIO_new(BIO_s_file()); |
0f113f3e MC |
463 | if (in == NULL) { |
464 | SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, ERR_R_BUF_LIB); | |
465 | goto end; | |
466 | } | |
467 | ||
468 | if (BIO_read_filename(in, file) <= 0) { | |
469 | SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, ERR_R_SYS_LIB); | |
470 | goto end; | |
471 | } | |
472 | if (type == SSL_FILETYPE_ASN1) { | |
473 | j = ERR_R_ASN1_LIB; | |
474 | rsa = d2i_RSAPrivateKey_bio(in, NULL); | |
475 | } else if (type == SSL_FILETYPE_PEM) { | |
476 | j = ERR_R_PEM_LIB; | |
477 | rsa = PEM_read_bio_RSAPrivateKey(in, NULL, | |
478 | ctx->default_passwd_callback, | |
479 | ctx->default_passwd_callback_userdata); | |
480 | } else { | |
481 | SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE); | |
482 | goto end; | |
483 | } | |
484 | if (rsa == NULL) { | |
485 | SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE, j); | |
486 | goto end; | |
487 | } | |
488 | ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa); | |
489 | RSA_free(rsa); | |
490 | end: | |
ca3a82c3 | 491 | BIO_free(in); |
0f113f3e MC |
492 | return (ret); |
493 | } | |
0f113f3e MC |
494 | |
495 | int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, | |
496 | long len) | |
497 | { | |
498 | int ret; | |
499 | const unsigned char *p; | |
500 | RSA *rsa; | |
501 | ||
502 | p = d; | |
503 | if ((rsa = d2i_RSAPrivateKey(NULL, &p, (long)len)) == NULL) { | |
504 | SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1, ERR_R_ASN1_LIB); | |
505 | return (0); | |
506 | } | |
507 | ||
508 | ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa); | |
509 | RSA_free(rsa); | |
510 | return (ret); | |
511 | } | |
512 | #endif /* !OPENSSL_NO_RSA */ | |
d02b48c6 | 513 | |
6b691a5c | 514 | int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) |
0f113f3e MC |
515 | { |
516 | if (pkey == NULL) { | |
517 | SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); | |
518 | return (0); | |
519 | } | |
0f113f3e MC |
520 | return (ssl_set_pkey(ctx->cert, pkey)); |
521 | } | |
d02b48c6 | 522 | |
303c0028 | 523 | int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) |
0f113f3e MC |
524 | { |
525 | int j, ret = 0; | |
526 | BIO *in; | |
527 | EVP_PKEY *pkey = NULL; | |
528 | ||
9982cbbb | 529 | in = BIO_new(BIO_s_file()); |
0f113f3e MC |
530 | if (in == NULL) { |
531 | SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB); | |
532 | goto end; | |
533 | } | |
534 | ||
535 | if (BIO_read_filename(in, file) <= 0) { | |
536 | SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_SYS_LIB); | |
537 | goto end; | |
538 | } | |
539 | if (type == SSL_FILETYPE_PEM) { | |
540 | j = ERR_R_PEM_LIB; | |
541 | pkey = PEM_read_bio_PrivateKey(in, NULL, | |
542 | ctx->default_passwd_callback, | |
543 | ctx->default_passwd_callback_userdata); | |
544 | } else if (type == SSL_FILETYPE_ASN1) { | |
545 | j = ERR_R_ASN1_LIB; | |
546 | pkey = d2i_PrivateKey_bio(in, NULL); | |
547 | } else { | |
548 | SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE); | |
549 | goto end; | |
550 | } | |
551 | if (pkey == NULL) { | |
552 | SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, j); | |
553 | goto end; | |
554 | } | |
555 | ret = SSL_CTX_use_PrivateKey(ctx, pkey); | |
556 | EVP_PKEY_free(pkey); | |
557 | end: | |
ca3a82c3 | 558 | BIO_free(in); |
0f113f3e MC |
559 | return (ret); |
560 | } | |
d02b48c6 | 561 | |
0f113f3e MC |
562 | int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, |
563 | const unsigned char *d, long len) | |
564 | { | |
565 | int ret; | |
566 | const unsigned char *p; | |
567 | EVP_PKEY *pkey; | |
d02b48c6 | 568 | |
0f113f3e MC |
569 | p = d; |
570 | if ((pkey = d2i_PrivateKey(type, NULL, &p, (long)len)) == NULL) { | |
571 | SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1, ERR_R_ASN1_LIB); | |
572 | return (0); | |
573 | } | |
d02b48c6 | 574 | |
0f113f3e MC |
575 | ret = SSL_CTX_use_PrivateKey(ctx, pkey); |
576 | EVP_PKEY_free(pkey); | |
577 | return (ret); | |
578 | } | |
d02b48c6 | 579 | |
0f113f3e MC |
580 | /* |
581 | * Read a file that contains our certificate in "PEM" format, possibly | |
582 | * followed by a sequence of CA certificates that should be sent to the peer | |
583 | * in the Certificate message. | |
b3ca645f | 584 | */ |
fae4772c | 585 | static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file) |
0f113f3e MC |
586 | { |
587 | BIO *in; | |
588 | int ret = 0; | |
589 | X509 *x = NULL; | |
a974e64a MC |
590 | pem_password_cb *passwd_callback; |
591 | void *passwd_callback_userdata; | |
0f113f3e MC |
592 | |
593 | ERR_clear_error(); /* clear error stack for | |
594 | * SSL_CTX_use_certificate() */ | |
595 | ||
a974e64a MC |
596 | if (ctx != NULL) { |
597 | passwd_callback = ctx->default_passwd_callback; | |
598 | passwd_callback_userdata = ctx->default_passwd_callback_userdata; | |
599 | } else { | |
600 | passwd_callback = ssl->default_passwd_callback; | |
601 | passwd_callback_userdata = ssl->default_passwd_callback_userdata; | |
602 | } | |
603 | ||
9982cbbb | 604 | in = BIO_new(BIO_s_file()); |
0f113f3e | 605 | if (in == NULL) { |
fae4772c | 606 | SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB); |
0f113f3e MC |
607 | goto end; |
608 | } | |
609 | ||
610 | if (BIO_read_filename(in, file) <= 0) { | |
fae4772c | 611 | SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_SYS_LIB); |
0f113f3e MC |
612 | goto end; |
613 | } | |
614 | ||
a974e64a MC |
615 | x = PEM_read_bio_X509_AUX(in, NULL, passwd_callback, |
616 | passwd_callback_userdata); | |
0f113f3e | 617 | if (x == NULL) { |
fae4772c | 618 | SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB); |
0f113f3e MC |
619 | goto end; |
620 | } | |
621 | ||
fae4772c DSH |
622 | if (ctx) |
623 | ret = SSL_CTX_use_certificate(ctx, x); | |
624 | else | |
625 | ret = SSL_use_certificate(ssl, x); | |
0f113f3e MC |
626 | |
627 | if (ERR_peek_error() != 0) | |
628 | ret = 0; /* Key/certificate mismatch doesn't imply | |
629 | * ret==0 ... */ | |
630 | if (ret) { | |
631 | /* | |
632 | * If we could set up our certificate, now proceed to the CA | |
633 | * certificates. | |
634 | */ | |
635 | X509 *ca; | |
636 | int r; | |
637 | unsigned long err; | |
638 | ||
fae4772c DSH |
639 | if (ctx) |
640 | r = SSL_CTX_clear_chain_certs(ctx); | |
641 | else | |
642 | r = SSL_clear_chain_certs(ssl); | |
643 | ||
644 | if (r == 0) { | |
69f68237 MC |
645 | ret = 0; |
646 | goto end; | |
647 | } | |
0f113f3e | 648 | |
a974e64a MC |
649 | while ((ca = PEM_read_bio_X509(in, NULL, passwd_callback, |
650 | passwd_callback_userdata)) | |
a230b26e | 651 | != NULL) { |
fae4772c DSH |
652 | if (ctx) |
653 | r = SSL_CTX_add0_chain_cert(ctx, ca); | |
654 | else | |
655 | r = SSL_add0_chain_cert(ssl, ca); | |
656 | /* | |
657 | * Note that we must not free ca if it was successfully added to | |
658 | * the chain (while we must free the main certificate, since its | |
659 | * reference count is increased by SSL_CTX_use_certificate). | |
660 | */ | |
0f113f3e MC |
661 | if (!r) { |
662 | X509_free(ca); | |
663 | ret = 0; | |
664 | goto end; | |
665 | } | |
0f113f3e MC |
666 | } |
667 | /* When the while loop ends, it's usually just EOF. */ | |
668 | err = ERR_peek_last_error(); | |
669 | if (ERR_GET_LIB(err) == ERR_LIB_PEM | |
670 | && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) | |
671 | ERR_clear_error(); | |
672 | else | |
673 | ret = 0; /* some real error */ | |
674 | } | |
675 | ||
676 | end: | |
25aaa98a | 677 | X509_free(x); |
ca3a82c3 | 678 | BIO_free(in); |
0f113f3e MC |
679 | return (ret); |
680 | } | |
fae4772c DSH |
681 | |
682 | int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) | |
683 | { | |
684 | return use_certificate_chain_file(ctx, NULL, file); | |
685 | } | |
686 | ||
687 | int SSL_use_certificate_chain_file(SSL *ssl, const char *file) | |
688 | { | |
689 | return use_certificate_chain_file(NULL, ssl, file); | |
690 | } | |
a9e1c50b | 691 | |
a398f821 | 692 | static int serverinfo_find_extension(const unsigned char *serverinfo, |
0f113f3e MC |
693 | size_t serverinfo_length, |
694 | unsigned int extension_type, | |
695 | const unsigned char **extension_data, | |
696 | size_t *extension_length) | |
697 | { | |
698 | *extension_data = NULL; | |
699 | *extension_length = 0; | |
700 | if (serverinfo == NULL || serverinfo_length == 0) | |
fae11ec7 | 701 | return -1; |
0f113f3e MC |
702 | for (;;) { |
703 | unsigned int type = 0; | |
704 | size_t len = 0; | |
705 | ||
706 | /* end of serverinfo */ | |
707 | if (serverinfo_length == 0) | |
fae11ec7 | 708 | return 0; /* Extension not found */ |
0f113f3e MC |
709 | |
710 | /* read 2-byte type field */ | |
711 | if (serverinfo_length < 2) | |
fae11ec7 | 712 | return -1; /* Error */ |
0f113f3e MC |
713 | type = (serverinfo[0] << 8) + serverinfo[1]; |
714 | serverinfo += 2; | |
715 | serverinfo_length -= 2; | |
716 | ||
717 | /* read 2-byte len field */ | |
718 | if (serverinfo_length < 2) | |
fae11ec7 | 719 | return -1; /* Error */ |
0f113f3e MC |
720 | len = (serverinfo[0] << 8) + serverinfo[1]; |
721 | serverinfo += 2; | |
722 | serverinfo_length -= 2; | |
723 | ||
724 | if (len > serverinfo_length) | |
fae11ec7 | 725 | return -1; /* Error */ |
0f113f3e MC |
726 | |
727 | if (type == extension_type) { | |
728 | *extension_data = serverinfo; | |
729 | *extension_length = len; | |
730 | return 1; /* Success */ | |
731 | } | |
732 | ||
733 | serverinfo += len; | |
734 | serverinfo_length -= len; | |
735 | } | |
c6ef15c4 | 736 | /* Unreachable */ |
0f113f3e | 737 | } |
a398f821 | 738 | |
de2a9e38 | 739 | static int serverinfo_srv_parse_cb(SSL *s, unsigned int ext_type, |
0f113f3e MC |
740 | const unsigned char *in, |
741 | size_t inlen, int *al, void *arg) | |
742 | { | |
0a602875 | 743 | |
0f113f3e MC |
744 | if (inlen != 0) { |
745 | *al = SSL_AD_DECODE_ERROR; | |
746 | return 0; | |
747 | } | |
0a602875 | 748 | |
0f113f3e MC |
749 | return 1; |
750 | } | |
9cd50f73 | 751 | |
de2a9e38 | 752 | static int serverinfo_srv_add_cb(SSL *s, unsigned int ext_type, |
0f113f3e MC |
753 | const unsigned char **out, size_t *outlen, |
754 | int *al, void *arg) | |
755 | { | |
756 | const unsigned char *serverinfo = NULL; | |
757 | size_t serverinfo_length = 0; | |
758 | ||
759 | /* Is there serverinfo data for the chosen server cert? */ | |
760 | if ((ssl_get_server_cert_serverinfo(s, &serverinfo, | |
761 | &serverinfo_length)) != 0) { | |
762 | /* Find the relevant extension from the serverinfo */ | |
763 | int retval = serverinfo_find_extension(serverinfo, serverinfo_length, | |
764 | ext_type, out, outlen); | |
fae11ec7 KR |
765 | if (retval == -1) { |
766 | *al = SSL_AD_DECODE_ERROR; | |
767 | return -1; /* Error */ | |
768 | } | |
0f113f3e | 769 | if (retval == 0) |
fae11ec7 | 770 | return 0; /* No extension found, don't send extension */ |
0f113f3e MC |
771 | return 1; /* Send extension */ |
772 | } | |
5f18bc58 | 773 | return 0; /* No serverinfo data found, don't send |
0f113f3e MC |
774 | * extension */ |
775 | } | |
776 | ||
777 | /* | |
778 | * With a NULL context, this function just checks that the serverinfo data | |
779 | * parses correctly. With a non-NULL context, it registers callbacks for | |
780 | * the included extensions. | |
781 | */ | |
782 | static int serverinfo_process_buffer(const unsigned char *serverinfo, | |
783 | size_t serverinfo_length, SSL_CTX *ctx) | |
784 | { | |
785 | if (serverinfo == NULL || serverinfo_length == 0) | |
786 | return 0; | |
787 | for (;;) { | |
788 | unsigned int ext_type = 0; | |
789 | size_t len = 0; | |
790 | ||
791 | /* end of serverinfo */ | |
792 | if (serverinfo_length == 0) | |
793 | return 1; | |
794 | ||
795 | /* read 2-byte type field */ | |
796 | if (serverinfo_length < 2) | |
797 | return 0; | |
798 | /* FIXME: check for types we understand explicitly? */ | |
799 | ||
800 | /* Register callbacks for extensions */ | |
801 | ext_type = (serverinfo[0] << 8) + serverinfo[1]; | |
5f18bc58 TS |
802 | if (ctx) { |
803 | int have_ext_cbs = 0; | |
804 | size_t i; | |
805 | custom_ext_methods *exts = &ctx->cert->srv_ext; | |
806 | custom_ext_method *meth = exts->meths; | |
807 | ||
5f18bc58 TS |
808 | for (i = 0; i < exts->meths_count; i++, meth++) { |
809 | if (ext_type == meth->ext_type) { | |
810 | have_ext_cbs = 1; | |
811 | break; | |
812 | } | |
813 | } | |
814 | ||
815 | if (!have_ext_cbs && !SSL_CTX_add_server_custom_ext(ctx, ext_type, | |
816 | serverinfo_srv_add_cb, | |
817 | NULL, NULL, | |
818 | serverinfo_srv_parse_cb, | |
819 | NULL)) | |
820 | return 0; | |
821 | } | |
0f113f3e MC |
822 | |
823 | serverinfo += 2; | |
824 | serverinfo_length -= 2; | |
825 | ||
826 | /* read 2-byte len field */ | |
827 | if (serverinfo_length < 2) | |
828 | return 0; | |
829 | len = (serverinfo[0] << 8) + serverinfo[1]; | |
830 | serverinfo += 2; | |
831 | serverinfo_length -= 2; | |
832 | ||
833 | if (len > serverinfo_length) | |
834 | return 0; | |
835 | ||
836 | serverinfo += len; | |
837 | serverinfo_length -= len; | |
838 | } | |
839 | } | |
a398f821 | 840 | |
a398f821 | 841 | int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo, |
0f113f3e MC |
842 | size_t serverinfo_length) |
843 | { | |
844 | unsigned char *new_serverinfo; | |
845 | ||
846 | if (ctx == NULL || serverinfo == NULL || serverinfo_length == 0) { | |
847 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, ERR_R_PASSED_NULL_PARAMETER); | |
848 | return 0; | |
849 | } | |
850 | if (!serverinfo_process_buffer(serverinfo, serverinfo_length, NULL)) { | |
851 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, SSL_R_INVALID_SERVERINFO_DATA); | |
852 | return 0; | |
853 | } | |
0f113f3e MC |
854 | if (ctx->cert->key == NULL) { |
855 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, ERR_R_INTERNAL_ERROR); | |
856 | return 0; | |
857 | } | |
858 | new_serverinfo = OPENSSL_realloc(ctx->cert->key->serverinfo, | |
859 | serverinfo_length); | |
860 | if (new_serverinfo == NULL) { | |
861 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, ERR_R_MALLOC_FAILURE); | |
862 | return 0; | |
863 | } | |
864 | ctx->cert->key->serverinfo = new_serverinfo; | |
865 | memcpy(ctx->cert->key->serverinfo, serverinfo, serverinfo_length); | |
866 | ctx->cert->key->serverinfo_length = serverinfo_length; | |
867 | ||
868 | /* | |
869 | * Now that the serverinfo is validated and stored, go ahead and | |
870 | * register callbacks. | |
871 | */ | |
872 | if (!serverinfo_process_buffer(serverinfo, serverinfo_length, ctx)) { | |
873 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, SSL_R_INVALID_SERVERINFO_DATA); | |
874 | return 0; | |
875 | } | |
876 | return 1; | |
877 | } | |
878 | ||
a398f821 | 879 | int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file) |
0f113f3e MC |
880 | { |
881 | unsigned char *serverinfo = NULL; | |
7c0ef843 | 882 | unsigned char *tmp; |
0f113f3e MC |
883 | size_t serverinfo_length = 0; |
884 | unsigned char *extension = 0; | |
885 | long extension_length = 0; | |
886 | char *name = NULL; | |
887 | char *header = NULL; | |
888 | char namePrefix[] = "SERVERINFO FOR "; | |
889 | int ret = 0; | |
890 | BIO *bin = NULL; | |
891 | size_t num_extensions = 0; | |
892 | ||
893 | if (ctx == NULL || file == NULL) { | |
a230b26e | 894 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_PASSED_NULL_PARAMETER); |
0f113f3e MC |
895 | goto end; |
896 | } | |
897 | ||
9982cbbb | 898 | bin = BIO_new(BIO_s_file()); |
0f113f3e MC |
899 | if (bin == NULL) { |
900 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_BUF_LIB); | |
901 | goto end; | |
902 | } | |
903 | if (BIO_read_filename(bin, file) <= 0) { | |
904 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_SYS_LIB); | |
905 | goto end; | |
906 | } | |
907 | ||
908 | for (num_extensions = 0;; num_extensions++) { | |
909 | if (PEM_read_bio(bin, &name, &header, &extension, &extension_length) | |
910 | == 0) { | |
911 | /* | |
912 | * There must be at least one extension in this file | |
913 | */ | |
914 | if (num_extensions == 0) { | |
915 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, | |
916 | SSL_R_NO_PEM_EXTENSIONS); | |
917 | goto end; | |
918 | } else /* End of file, we're done */ | |
919 | break; | |
920 | } | |
921 | /* Check that PEM name starts with "BEGIN SERVERINFO FOR " */ | |
922 | if (strlen(name) < strlen(namePrefix)) { | |
a230b26e | 923 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_PEM_NAME_TOO_SHORT); |
0f113f3e MC |
924 | goto end; |
925 | } | |
926 | if (strncmp(name, namePrefix, strlen(namePrefix)) != 0) { | |
927 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, | |
928 | SSL_R_PEM_NAME_BAD_PREFIX); | |
929 | goto end; | |
930 | } | |
931 | /* | |
932 | * Check that the decoded PEM data is plausible (valid length field) | |
933 | */ | |
934 | if (extension_length < 4 | |
935 | || (extension[2] << 8) + extension[3] != extension_length - 4) { | |
936 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_BAD_DATA); | |
937 | goto end; | |
938 | } | |
939 | /* Append the decoded extension to the serverinfo buffer */ | |
a230b26e | 940 | tmp = OPENSSL_realloc(serverinfo, serverinfo_length + extension_length); |
7c0ef843 | 941 | if (tmp == NULL) { |
0f113f3e MC |
942 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_MALLOC_FAILURE); |
943 | goto end; | |
944 | } | |
7c0ef843 | 945 | serverinfo = tmp; |
0f113f3e MC |
946 | memcpy(serverinfo + serverinfo_length, extension, extension_length); |
947 | serverinfo_length += extension_length; | |
948 | ||
949 | OPENSSL_free(name); | |
950 | name = NULL; | |
951 | OPENSSL_free(header); | |
952 | header = NULL; | |
953 | OPENSSL_free(extension); | |
954 | extension = NULL; | |
955 | } | |
956 | ||
957 | ret = SSL_CTX_use_serverinfo(ctx, serverinfo, serverinfo_length); | |
958 | end: | |
959 | /* SSL_CTX_use_serverinfo makes a local copy of the serverinfo. */ | |
960 | OPENSSL_free(name); | |
961 | OPENSSL_free(header); | |
962 | OPENSSL_free(extension); | |
963 | OPENSSL_free(serverinfo); | |
ca3a82c3 | 964 | BIO_free(bin); |
0f113f3e MC |
965 | return ret; |
966 | } |