]>
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> | |
1608d658 | 11 | #include <assert.h> |
7b63c0fa | 12 | #include "ssl_locl.h" |
84c34ba8 | 13 | #include "packet_locl.h" |
ec577822 BM |
14 | #include <openssl/bio.h> |
15 | #include <openssl/objects.h> | |
16 | #include <openssl/evp.h> | |
17 | #include <openssl/x509.h> | |
18 | #include <openssl/pem.h> | |
d02b48c6 | 19 | |
d02b48c6 RE |
20 | static int ssl_set_cert(CERT *c, X509 *x509); |
21 | static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); | |
6b691a5c | 22 | int SSL_use_certificate(SSL *ssl, X509 *x) |
0f113f3e MC |
23 | { |
24 | int rv; | |
25 | if (x == NULL) { | |
26 | SSLerr(SSL_F_SSL_USE_CERTIFICATE, ERR_R_PASSED_NULL_PARAMETER); | |
27 | return (0); | |
28 | } | |
29 | rv = ssl_security_cert(ssl, NULL, x, 0, 1); | |
30 | if (rv != 1) { | |
31 | SSLerr(SSL_F_SSL_USE_CERTIFICATE, rv); | |
32 | return 0; | |
33 | } | |
34 | ||
0f113f3e MC |
35 | return (ssl_set_cert(ssl->cert, x)); |
36 | } | |
d02b48c6 | 37 | |
303c0028 | 38 | int SSL_use_certificate_file(SSL *ssl, const char *file, int type) |
0f113f3e MC |
39 | { |
40 | int j; | |
41 | BIO *in; | |
42 | int ret = 0; | |
43 | X509 *x = NULL; | |
44 | ||
9982cbbb | 45 | in = BIO_new(BIO_s_file()); |
0f113f3e MC |
46 | if (in == NULL) { |
47 | SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_BUF_LIB); | |
48 | goto end; | |
49 | } | |
50 | ||
51 | if (BIO_read_filename(in, file) <= 0) { | |
52 | SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_SYS_LIB); | |
53 | goto end; | |
54 | } | |
55 | if (type == SSL_FILETYPE_ASN1) { | |
56 | j = ERR_R_ASN1_LIB; | |
57 | x = d2i_X509_bio(in, NULL); | |
58 | } else if (type == SSL_FILETYPE_PEM) { | |
59 | j = ERR_R_PEM_LIB; | |
d61461a7 P |
60 | x = PEM_read_bio_X509(in, NULL, ssl->default_passwd_callback, |
61 | ssl->default_passwd_callback_userdata); | |
0f113f3e MC |
62 | } else { |
63 | SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, SSL_R_BAD_SSL_FILETYPE); | |
64 | goto end; | |
65 | } | |
66 | ||
67 | if (x == NULL) { | |
68 | SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, j); | |
69 | goto end; | |
70 | } | |
71 | ||
72 | ret = SSL_use_certificate(ssl, x); | |
73 | end: | |
222561fe | 74 | X509_free(x); |
ca3a82c3 | 75 | BIO_free(in); |
0f113f3e MC |
76 | return (ret); |
77 | } | |
d02b48c6 | 78 | |
875a644a | 79 | int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len) |
0f113f3e MC |
80 | { |
81 | X509 *x; | |
82 | int ret; | |
83 | ||
84 | x = d2i_X509(NULL, &d, (long)len); | |
85 | if (x == NULL) { | |
86 | SSLerr(SSL_F_SSL_USE_CERTIFICATE_ASN1, ERR_R_ASN1_LIB); | |
87 | return (0); | |
88 | } | |
89 | ||
90 | ret = SSL_use_certificate(ssl, x); | |
91 | X509_free(x); | |
92 | return (ret); | |
93 | } | |
d02b48c6 | 94 | |
bc36ee62 | 95 | #ifndef OPENSSL_NO_RSA |
6b691a5c | 96 | int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) |
0f113f3e MC |
97 | { |
98 | EVP_PKEY *pkey; | |
99 | int ret; | |
100 | ||
101 | if (rsa == NULL) { | |
102 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); | |
103 | return (0); | |
104 | } | |
0f113f3e MC |
105 | if ((pkey = EVP_PKEY_new()) == NULL) { |
106 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY, ERR_R_EVP_LIB); | |
107 | return (0); | |
108 | } | |
109 | ||
110 | RSA_up_ref(rsa); | |
5f3d93e4 MC |
111 | if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) { |
112 | RSA_free(rsa); | |
563c1ec6 | 113 | EVP_PKEY_free(pkey); |
5f3d93e4 MC |
114 | return 0; |
115 | } | |
0f113f3e MC |
116 | |
117 | ret = ssl_set_pkey(ssl->cert, pkey); | |
118 | EVP_PKEY_free(pkey); | |
119 | return (ret); | |
120 | } | |
d02b48c6 RE |
121 | #endif |
122 | ||
6b691a5c | 123 | static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) |
0f113f3e MC |
124 | { |
125 | int i; | |
bc71f910 | 126 | i = ssl_cert_type(NULL, pkey); |
0f113f3e MC |
127 | if (i < 0) { |
128 | SSLerr(SSL_F_SSL_SET_PKEY, SSL_R_UNKNOWN_CERTIFICATE_TYPE); | |
129 | return (0); | |
130 | } | |
131 | ||
132 | if (c->pkeys[i].x509 != NULL) { | |
133 | EVP_PKEY *pktmp; | |
8382fd3a | 134 | pktmp = X509_get0_pubkey(c->pkeys[i].x509); |
5f3d93e4 MC |
135 | if (pktmp == NULL) { |
136 | SSLerr(SSL_F_SSL_SET_PKEY, ERR_R_MALLOC_FAILURE); | |
5f3d93e4 MC |
137 | return 0; |
138 | } | |
139 | /* | |
140 | * The return code from EVP_PKEY_copy_parameters is deliberately | |
141 | * ignored. Some EVP_PKEY types cannot do this. | |
142 | */ | |
0f113f3e | 143 | EVP_PKEY_copy_parameters(pktmp, pkey); |
0f113f3e | 144 | ERR_clear_error(); |
dfeab068 | 145 | |
bc36ee62 | 146 | #ifndef OPENSSL_NO_RSA |
0f113f3e MC |
147 | /* |
148 | * Don't check the public/private key, this is mostly for smart | |
149 | * cards. | |
150 | */ | |
3aeb9348 | 151 | if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA |
a230b26e | 152 | && RSA_flags(EVP_PKEY_get0_RSA(pkey)) & RSA_METHOD_FLAG_NO_CHECK) ; |
0f113f3e | 153 | else |
58964a49 | 154 | #endif |
0f113f3e MC |
155 | if (!X509_check_private_key(c->pkeys[i].x509, pkey)) { |
156 | X509_free(c->pkeys[i].x509); | |
157 | c->pkeys[i].x509 = NULL; | |
158 | return 0; | |
159 | } | |
160 | } | |
161 | ||
25aaa98a | 162 | EVP_PKEY_free(c->pkeys[i].privatekey); |
3aeb9348 | 163 | EVP_PKEY_up_ref(pkey); |
0f113f3e MC |
164 | c->pkeys[i].privatekey = pkey; |
165 | c->key = &(c->pkeys[i]); | |
0f113f3e MC |
166 | return (1); |
167 | } | |
d02b48c6 | 168 | |
bc36ee62 | 169 | #ifndef OPENSSL_NO_RSA |
303c0028 | 170 | int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) |
0f113f3e MC |
171 | { |
172 | int j, ret = 0; | |
173 | BIO *in; | |
174 | RSA *rsa = NULL; | |
175 | ||
9982cbbb | 176 | in = BIO_new(BIO_s_file()); |
0f113f3e MC |
177 | if (in == NULL) { |
178 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, ERR_R_BUF_LIB); | |
179 | goto end; | |
180 | } | |
181 | ||
182 | if (BIO_read_filename(in, file) <= 0) { | |
183 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, ERR_R_SYS_LIB); | |
184 | goto end; | |
185 | } | |
186 | if (type == SSL_FILETYPE_ASN1) { | |
187 | j = ERR_R_ASN1_LIB; | |
188 | rsa = d2i_RSAPrivateKey_bio(in, NULL); | |
189 | } else if (type == SSL_FILETYPE_PEM) { | |
190 | j = ERR_R_PEM_LIB; | |
191 | rsa = PEM_read_bio_RSAPrivateKey(in, NULL, | |
d61461a7 P |
192 | ssl->default_passwd_callback, |
193 | ssl->default_passwd_callback_userdata); | |
0f113f3e MC |
194 | } else { |
195 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, SSL_R_BAD_SSL_FILETYPE); | |
196 | goto end; | |
197 | } | |
198 | if (rsa == NULL) { | |
199 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE, j); | |
200 | goto end; | |
201 | } | |
202 | ret = SSL_use_RSAPrivateKey(ssl, rsa); | |
203 | RSA_free(rsa); | |
204 | end: | |
ca3a82c3 | 205 | BIO_free(in); |
0f113f3e MC |
206 | return (ret); |
207 | } | |
d02b48c6 | 208 | |
693b71fa | 209 | int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, long len) |
0f113f3e MC |
210 | { |
211 | int ret; | |
212 | const unsigned char *p; | |
213 | RSA *rsa; | |
214 | ||
215 | p = d; | |
216 | if ((rsa = d2i_RSAPrivateKey(NULL, &p, (long)len)) == NULL) { | |
217 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1, ERR_R_ASN1_LIB); | |
218 | return (0); | |
219 | } | |
220 | ||
221 | ret = SSL_use_RSAPrivateKey(ssl, rsa); | |
222 | RSA_free(rsa); | |
223 | return (ret); | |
224 | } | |
225 | #endif /* !OPENSSL_NO_RSA */ | |
d02b48c6 | 226 | |
6b691a5c | 227 | int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) |
0f113f3e MC |
228 | { |
229 | int ret; | |
230 | ||
231 | if (pkey == NULL) { | |
232 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY, ERR_R_PASSED_NULL_PARAMETER); | |
233 | return (0); | |
234 | } | |
0f113f3e MC |
235 | ret = ssl_set_pkey(ssl->cert, pkey); |
236 | return (ret); | |
237 | } | |
d02b48c6 | 238 | |
303c0028 | 239 | int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) |
0f113f3e MC |
240 | { |
241 | int j, ret = 0; | |
242 | BIO *in; | |
243 | EVP_PKEY *pkey = NULL; | |
244 | ||
9982cbbb | 245 | in = BIO_new(BIO_s_file()); |
0f113f3e MC |
246 | if (in == NULL) { |
247 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB); | |
248 | goto end; | |
249 | } | |
250 | ||
251 | if (BIO_read_filename(in, file) <= 0) { | |
252 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE, ERR_R_SYS_LIB); | |
253 | goto end; | |
254 | } | |
255 | if (type == SSL_FILETYPE_PEM) { | |
256 | j = ERR_R_PEM_LIB; | |
257 | pkey = PEM_read_bio_PrivateKey(in, NULL, | |
d61461a7 P |
258 | ssl->default_passwd_callback, |
259 | ssl->default_passwd_callback_userdata); | |
0f113f3e MC |
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 | { | |
84c34ba8 MC |
698 | PACKET pkt, data; |
699 | ||
0f113f3e MC |
700 | *extension_data = NULL; |
701 | *extension_length = 0; | |
702 | if (serverinfo == NULL || serverinfo_length == 0) | |
fae11ec7 | 703 | return -1; |
84c34ba8 MC |
704 | |
705 | if (!PACKET_buf_init(&pkt, serverinfo, serverinfo_length)) | |
706 | return -1; | |
707 | ||
0f113f3e MC |
708 | for (;;) { |
709 | unsigned int type = 0; | |
84c34ba8 | 710 | unsigned long context = 0; |
0f113f3e MC |
711 | |
712 | /* end of serverinfo */ | |
84c34ba8 | 713 | if (PACKET_remaining(&pkt) == 0) |
fae11ec7 | 714 | return 0; /* Extension not found */ |
0f113f3e | 715 | |
84c34ba8 MC |
716 | if (!PACKET_get_net_4(&pkt, &context) |
717 | || !PACKET_get_net_2(&pkt, &type) | |
718 | || !PACKET_get_length_prefixed_2(&pkt, &data)) | |
719 | return -1; | |
0f113f3e MC |
720 | |
721 | if (type == extension_type) { | |
84c34ba8 MC |
722 | *extension_data = PACKET_data(&data); |
723 | *extension_length = PACKET_remaining(&data);; | |
0f113f3e MC |
724 | return 1; /* Success */ |
725 | } | |
0f113f3e | 726 | } |
c6ef15c4 | 727 | /* Unreachable */ |
0f113f3e | 728 | } |
a398f821 | 729 | |
84c34ba8 MC |
730 | static int serverinfoex_srv_parse_cb(SSL *s, unsigned int ext_type, |
731 | unsigned int context, | |
732 | const unsigned char *in, | |
733 | size_t inlen, X509 *x, size_t chainidx, | |
734 | int *al, void *arg) | |
0f113f3e | 735 | { |
0a602875 | 736 | |
0f113f3e MC |
737 | if (inlen != 0) { |
738 | *al = SSL_AD_DECODE_ERROR; | |
739 | return 0; | |
740 | } | |
0a602875 | 741 | |
0f113f3e MC |
742 | return 1; |
743 | } | |
9cd50f73 | 744 | |
84c34ba8 MC |
745 | static int serverinfo_srv_parse_cb(SSL *s, unsigned int ext_type, |
746 | const unsigned char *in, | |
747 | size_t inlen, int *al, void *arg) | |
748 | { | |
749 | return serverinfoex_srv_parse_cb(s, ext_type, 0, in, inlen, NULL, 0, al, | |
750 | arg); | |
751 | } | |
752 | ||
753 | static int serverinfoex_srv_add_cb(SSL *s, unsigned int ext_type, | |
754 | unsigned int context, | |
755 | const unsigned char **out, | |
756 | size_t *outlen, X509 *x, size_t chainidx, | |
757 | int *al, void *arg) | |
0f113f3e MC |
758 | { |
759 | const unsigned char *serverinfo = NULL; | |
760 | size_t serverinfo_length = 0; | |
761 | ||
f233a9d1 MC |
762 | /* We only support extensions for the first Certificate */ |
763 | if ((context & SSL_EXT_TLS1_3_CERTIFICATE) != 0 && chainidx > 0) | |
764 | return 0; | |
765 | ||
0f113f3e MC |
766 | /* Is there serverinfo data for the chosen server cert? */ |
767 | if ((ssl_get_server_cert_serverinfo(s, &serverinfo, | |
768 | &serverinfo_length)) != 0) { | |
769 | /* Find the relevant extension from the serverinfo */ | |
770 | int retval = serverinfo_find_extension(serverinfo, serverinfo_length, | |
771 | ext_type, out, outlen); | |
fae11ec7 KR |
772 | if (retval == -1) { |
773 | *al = SSL_AD_DECODE_ERROR; | |
774 | return -1; /* Error */ | |
775 | } | |
0f113f3e | 776 | if (retval == 0) |
fae11ec7 | 777 | return 0; /* No extension found, don't send extension */ |
0f113f3e MC |
778 | return 1; /* Send extension */ |
779 | } | |
5f18bc58 | 780 | return 0; /* No serverinfo data found, don't send |
0f113f3e MC |
781 | * extension */ |
782 | } | |
783 | ||
84c34ba8 MC |
784 | static int serverinfo_srv_add_cb(SSL *s, unsigned int ext_type, |
785 | const unsigned char **out, size_t *outlen, | |
786 | int *al, void *arg) | |
787 | { | |
788 | return serverinfoex_srv_add_cb(s, ext_type, 0, out, outlen, NULL, 0, al, | |
789 | arg); | |
790 | } | |
791 | ||
0f113f3e MC |
792 | /* |
793 | * With a NULL context, this function just checks that the serverinfo data | |
794 | * parses correctly. With a non-NULL context, it registers callbacks for | |
795 | * the included extensions. | |
796 | */ | |
84c34ba8 MC |
797 | static int serverinfo_process_buffer(unsigned int version, |
798 | const unsigned char *serverinfo, | |
0f113f3e MC |
799 | size_t serverinfo_length, SSL_CTX *ctx) |
800 | { | |
84c34ba8 MC |
801 | PACKET pkt; |
802 | ||
0f113f3e MC |
803 | if (serverinfo == NULL || serverinfo_length == 0) |
804 | return 0; | |
0f113f3e | 805 | |
2698bbfe | 806 | if (version != SSL_SERVERINFOV1 && version != SSL_SERVERINFOV2) |
84c34ba8 | 807 | return 0; |
0f113f3e | 808 | |
84c34ba8 MC |
809 | if (!PACKET_buf_init(&pkt, serverinfo, serverinfo_length)) |
810 | return 0; | |
0f113f3e | 811 | |
84c34ba8 MC |
812 | while (PACKET_remaining(&pkt)) { |
813 | unsigned long context = 0; | |
814 | unsigned int ext_type = 0; | |
815 | PACKET data; | |
0f113f3e | 816 | |
84c34ba8 MC |
817 | if (!PACKET_get_net_4(&pkt, &context) |
818 | || !PACKET_get_net_2(&pkt, &ext_type) | |
819 | || !PACKET_get_length_prefixed_2(&pkt, &data)) | |
0f113f3e MC |
820 | return 0; |
821 | ||
84c34ba8 MC |
822 | if (ctx == NULL) |
823 | continue; | |
824 | ||
2698bbfe | 825 | if (version == SSL_SERVERINFOV1) { |
84c34ba8 MC |
826 | if (!SSL_CTX_add_server_custom_ext(ctx, ext_type, |
827 | serverinfo_srv_add_cb, | |
828 | NULL, NULL, | |
829 | serverinfo_srv_parse_cb, | |
830 | NULL)) | |
831 | return 0; | |
832 | } else { | |
833 | if (!SSL_CTX_add_custom_ext(ctx, ext_type, context, | |
834 | serverinfoex_srv_add_cb, | |
835 | NULL, NULL, | |
836 | serverinfoex_srv_parse_cb, | |
837 | NULL)) | |
838 | return 0; | |
839 | } | |
0f113f3e | 840 | } |
84c34ba8 MC |
841 | |
842 | return 1; | |
0f113f3e | 843 | } |
a398f821 | 844 | |
84c34ba8 MC |
845 | int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version, |
846 | const unsigned char *serverinfo, | |
847 | size_t serverinfo_length) | |
0f113f3e MC |
848 | { |
849 | unsigned char *new_serverinfo; | |
850 | ||
851 | if (ctx == NULL || serverinfo == NULL || serverinfo_length == 0) { | |
84c34ba8 | 852 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, ERR_R_PASSED_NULL_PARAMETER); |
0f113f3e MC |
853 | return 0; |
854 | } | |
84c34ba8 MC |
855 | if (!serverinfo_process_buffer(version, serverinfo, serverinfo_length, |
856 | NULL)) { | |
857 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, SSL_R_INVALID_SERVERINFO_DATA); | |
0f113f3e MC |
858 | return 0; |
859 | } | |
0f113f3e | 860 | if (ctx->cert->key == NULL) { |
84c34ba8 | 861 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, ERR_R_INTERNAL_ERROR); |
0f113f3e MC |
862 | return 0; |
863 | } | |
864 | new_serverinfo = OPENSSL_realloc(ctx->cert->key->serverinfo, | |
865 | serverinfo_length); | |
866 | if (new_serverinfo == NULL) { | |
84c34ba8 | 867 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
868 | return 0; |
869 | } | |
870 | ctx->cert->key->serverinfo = new_serverinfo; | |
871 | memcpy(ctx->cert->key->serverinfo, serverinfo, serverinfo_length); | |
872 | ctx->cert->key->serverinfo_length = serverinfo_length; | |
873 | ||
874 | /* | |
875 | * Now that the serverinfo is validated and stored, go ahead and | |
876 | * register callbacks. | |
877 | */ | |
84c34ba8 MC |
878 | if (!serverinfo_process_buffer(version, serverinfo, serverinfo_length, |
879 | ctx)) { | |
880 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, SSL_R_INVALID_SERVERINFO_DATA); | |
0f113f3e MC |
881 | return 0; |
882 | } | |
883 | return 1; | |
884 | } | |
885 | ||
84c34ba8 MC |
886 | int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo, |
887 | size_t serverinfo_length) | |
888 | { | |
2698bbfe | 889 | return SSL_CTX_use_serverinfo_ex(ctx, SSL_SERVERINFOV1, serverinfo, |
84c34ba8 MC |
890 | serverinfo_length); |
891 | } | |
892 | ||
a398f821 | 893 | int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file) |
0f113f3e MC |
894 | { |
895 | unsigned char *serverinfo = NULL; | |
7c0ef843 | 896 | unsigned char *tmp; |
0f113f3e MC |
897 | size_t serverinfo_length = 0; |
898 | unsigned char *extension = 0; | |
899 | long extension_length = 0; | |
900 | char *name = NULL; | |
901 | char *header = NULL; | |
84c34ba8 MC |
902 | char namePrefix1[] = "SERVERINFO FOR "; |
903 | char namePrefix2[] = "SERVERINFOV2 FOR "; | |
0f113f3e MC |
904 | int ret = 0; |
905 | BIO *bin = NULL; | |
84c34ba8 | 906 | size_t num_extensions = 0, contextoff = 0; |
1608d658 | 907 | unsigned int version = 0; |
0f113f3e MC |
908 | |
909 | if (ctx == NULL || file == NULL) { | |
a230b26e | 910 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_PASSED_NULL_PARAMETER); |
0f113f3e MC |
911 | goto end; |
912 | } | |
913 | ||
9982cbbb | 914 | bin = BIO_new(BIO_s_file()); |
0f113f3e MC |
915 | if (bin == NULL) { |
916 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_BUF_LIB); | |
917 | goto end; | |
918 | } | |
919 | if (BIO_read_filename(bin, file) <= 0) { | |
920 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_SYS_LIB); | |
921 | goto end; | |
922 | } | |
923 | ||
924 | for (num_extensions = 0;; num_extensions++) { | |
925 | if (PEM_read_bio(bin, &name, &header, &extension, &extension_length) | |
926 | == 0) { | |
927 | /* | |
928 | * There must be at least one extension in this file | |
929 | */ | |
930 | if (num_extensions == 0) { | |
931 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, | |
932 | SSL_R_NO_PEM_EXTENSIONS); | |
933 | goto end; | |
934 | } else /* End of file, we're done */ | |
935 | break; | |
936 | } | |
937 | /* Check that PEM name starts with "BEGIN SERVERINFO FOR " */ | |
84c34ba8 | 938 | if (strlen(name) < strlen(namePrefix1)) { |
a230b26e | 939 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_PEM_NAME_TOO_SHORT); |
0f113f3e MC |
940 | goto end; |
941 | } | |
84c34ba8 | 942 | if (strncmp(name, namePrefix1, strlen(namePrefix1)) == 0) { |
2698bbfe | 943 | version = SSL_SERVERINFOV1; |
84c34ba8 MC |
944 | } else { |
945 | if (strlen(name) < strlen(namePrefix2)) { | |
946 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, | |
947 | SSL_R_PEM_NAME_TOO_SHORT); | |
948 | goto end; | |
949 | } | |
950 | if (strncmp(name, namePrefix2, strlen(namePrefix2)) != 0) { | |
951 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, | |
952 | SSL_R_PEM_NAME_BAD_PREFIX); | |
953 | goto end; | |
954 | } | |
2698bbfe | 955 | version = SSL_SERVERINFOV2; |
0f113f3e MC |
956 | } |
957 | /* | |
958 | * Check that the decoded PEM data is plausible (valid length field) | |
959 | */ | |
2698bbfe | 960 | if (version == SSL_SERVERINFOV1) { |
84c34ba8 MC |
961 | /* 4 byte header: 2 bytes type, 2 bytes len */ |
962 | if (extension_length < 4 | |
963 | || (extension[2] << 8) + extension[3] | |
964 | != extension_length - 4) { | |
965 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_BAD_DATA); | |
966 | goto end; | |
967 | } | |
968 | /* | |
969 | * File does not have a context value so we must take account of | |
970 | * this later. | |
971 | */ | |
972 | contextoff = 4; | |
973 | } else { | |
974 | /* 8 byte header: 4 bytes context, 2 bytes type, 2 bytes len */ | |
975 | if (extension_length < 8 | |
976 | || (extension[6] << 8) + extension[7] | |
977 | != extension_length - 8) { | |
978 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_BAD_DATA); | |
979 | goto end; | |
980 | } | |
0f113f3e MC |
981 | } |
982 | /* Append the decoded extension to the serverinfo buffer */ | |
84c34ba8 MC |
983 | tmp = OPENSSL_realloc(serverinfo, serverinfo_length + extension_length |
984 | + contextoff); | |
7c0ef843 | 985 | if (tmp == NULL) { |
0f113f3e MC |
986 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_MALLOC_FAILURE); |
987 | goto end; | |
988 | } | |
7c0ef843 | 989 | serverinfo = tmp; |
84c34ba8 MC |
990 | if (contextoff > 0) { |
991 | unsigned int synthcontext = SSL_EXT_CLIENT_HELLO | |
992 | | SSL_EXT_TLS1_2_SERVER_HELLO; | |
993 | unsigned char *sinfo = serverinfo + serverinfo_length; | |
994 | ||
995 | /* We know this only uses the last 2 bytes */ | |
996 | sinfo[0] = 0; | |
997 | sinfo[1] = 0; | |
998 | sinfo[2] = (synthcontext >> 8) & 0xff; | |
999 | sinfo[3] = synthcontext & 0xff; | |
1000 | } | |
1001 | memcpy(serverinfo + serverinfo_length + contextoff, | |
1002 | extension, extension_length); | |
1003 | serverinfo_length += extension_length + contextoff; | |
0f113f3e MC |
1004 | |
1005 | OPENSSL_free(name); | |
1006 | name = NULL; | |
1007 | OPENSSL_free(header); | |
1008 | header = NULL; | |
1009 | OPENSSL_free(extension); | |
1010 | extension = NULL; | |
1011 | } | |
1012 | ||
1608d658 TS |
1013 | assert(version != 0); |
1014 | if (version != 0) | |
1015 | ret = SSL_CTX_use_serverinfo_ex(ctx, version, serverinfo, | |
1016 | serverinfo_length); | |
0f113f3e MC |
1017 | end: |
1018 | /* SSL_CTX_use_serverinfo makes a local copy of the serverinfo. */ | |
1019 | OPENSSL_free(name); | |
1020 | OPENSSL_free(header); | |
1021 | OPENSSL_free(extension); | |
1022 | OPENSSL_free(serverinfo); | |
ca3a82c3 | 1023 | BIO_free(bin); |
0f113f3e MC |
1024 | return ret; |
1025 | } |