]>
Commit | Line | Data |
---|---|---|
d02b48c6 | 1 | /* ssl/ssl_rsa.c */ |
58964a49 | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
d02b48c6 RE |
3 | * All rights reserved. |
4 | * | |
5 | * This package is an SSL implementation written | |
6 | * by Eric Young (eay@cryptsoft.com). | |
7 | * The implementation was written so as to conform with Netscapes SSL. | |
8 | * | |
9 | * This library is free for commercial and non-commercial use as long as | |
10 | * the following conditions are aheared to. The following conditions | |
11 | * apply to all code found in this distribution, be it the RC4, RSA, | |
12 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation | |
13 | * included with this distribution is covered by the same copyright terms | |
14 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). | |
15 | * | |
16 | * Copyright remains Eric Young's, and as such any Copyright notices in | |
17 | * the code are not to be removed. | |
18 | * If this package is used in a product, Eric Young should be given attribution | |
19 | * as the author of the parts of the library used. | |
20 | * This can be in the form of a textual message at program startup or | |
21 | * in documentation (online or textual) provided with the package. | |
22 | * | |
23 | * Redistribution and use in source and binary forms, with or without | |
24 | * modification, are permitted provided that the following conditions | |
25 | * are met: | |
26 | * 1. Redistributions of source code must retain the copyright | |
27 | * notice, this list of conditions and the following disclaimer. | |
28 | * 2. Redistributions in binary form must reproduce the above copyright | |
29 | * notice, this list of conditions and the following disclaimer in the | |
30 | * documentation and/or other materials provided with the distribution. | |
31 | * 3. All advertising materials mentioning features or use of this software | |
32 | * must display the following acknowledgement: | |
33 | * "This product includes cryptographic software written by | |
34 | * Eric Young (eay@cryptsoft.com)" | |
35 | * The word 'cryptographic' can be left out if the rouines from the library | |
36 | * being used are not cryptographic related :-). | |
37 | * 4. If you include any Windows specific code (or a derivative thereof) from | |
38 | * the apps directory (application code) you must include an acknowledgement: | |
39 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | |
40 | * | |
41 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND | |
42 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
43 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
44 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
45 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
46 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
47 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
49 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
50 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
51 | * SUCH DAMAGE. | |
52 | * | |
53 | * The licence and distribution terms for any publically available version or | |
54 | * derivative of this code cannot be changed. i.e. this code cannot simply be | |
55 | * copied and put under another distribution licence | |
56 | * [including the GNU Public Licence.] | |
57 | */ | |
58 | ||
59 | #include <stdio.h> | |
7b63c0fa | 60 | #include "ssl_locl.h" |
ec577822 BM |
61 | #include <openssl/bio.h> |
62 | #include <openssl/objects.h> | |
63 | #include <openssl/evp.h> | |
64 | #include <openssl/x509.h> | |
65 | #include <openssl/pem.h> | |
d02b48c6 | 66 | |
d02b48c6 RE |
67 | static int ssl_set_cert(CERT *c, X509 *x509); |
68 | static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); | |
8a02a46a BL |
69 | #ifndef OPENSSL_NO_TLSEXT |
70 | static int ssl_set_authz(CERT *c, unsigned char *authz, | |
71 | size_t authz_length); | |
72 | #endif | |
6b691a5c | 73 | int SSL_use_certificate(SSL *ssl, X509 *x) |
d02b48c6 | 74 | { |
d02b48c6 RE |
75 | if (x == NULL) |
76 | { | |
77 | SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER); | |
78 | return(0); | |
79 | } | |
ca8e5b9b | 80 | if (!ssl_cert_inst(&ssl->cert)) |
d02b48c6 | 81 | { |
15d21c2d RE |
82 | SSLerr(SSL_F_SSL_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE); |
83 | return(0); | |
d02b48c6 | 84 | } |
15d21c2d | 85 | return(ssl_set_cert(ssl->cert,x)); |
d02b48c6 RE |
86 | } |
87 | ||
bc36ee62 | 88 | #ifndef OPENSSL_NO_STDIO |
303c0028 | 89 | int SSL_use_certificate_file(SSL *ssl, const char *file, int type) |
d02b48c6 RE |
90 | { |
91 | int j; | |
92 | BIO *in; | |
93 | int ret=0; | |
94 | X509 *x=NULL; | |
95 | ||
58964a49 | 96 | in=BIO_new(BIO_s_file_internal()); |
d02b48c6 RE |
97 | if (in == NULL) |
98 | { | |
99 | SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE,ERR_R_BUF_LIB); | |
100 | goto end; | |
101 | } | |
102 | ||
103 | if (BIO_read_filename(in,file) <= 0) | |
104 | { | |
d02b48c6 RE |
105 | SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE,ERR_R_SYS_LIB); |
106 | goto end; | |
107 | } | |
108 | if (type == SSL_FILETYPE_ASN1) | |
109 | { | |
110 | j=ERR_R_ASN1_LIB; | |
111 | x=d2i_X509_bio(in,NULL); | |
112 | } | |
113 | else if (type == SSL_FILETYPE_PEM) | |
114 | { | |
115 | j=ERR_R_PEM_LIB; | |
74678cc2 | 116 | x=PEM_read_bio_X509(in,NULL,ssl->ctx->default_passwd_callback,ssl->ctx->default_passwd_callback_userdata); |
d02b48c6 RE |
117 | } |
118 | else | |
119 | { | |
120 | SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE,SSL_R_BAD_SSL_FILETYPE); | |
121 | goto end; | |
122 | } | |
123 | ||
124 | if (x == NULL) | |
125 | { | |
126 | SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE,j); | |
127 | goto end; | |
128 | } | |
129 | ||
130 | ret=SSL_use_certificate(ssl,x); | |
131 | end: | |
132 | if (x != NULL) X509_free(x); | |
133 | if (in != NULL) BIO_free(in); | |
134 | return(ret); | |
135 | } | |
58964a49 | 136 | #endif |
d02b48c6 | 137 | |
875a644a | 138 | int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len) |
d02b48c6 RE |
139 | { |
140 | X509 *x; | |
141 | int ret; | |
142 | ||
143 | x=d2i_X509(NULL,&d,(long)len); | |
144 | if (x == NULL) | |
145 | { | |
146 | SSLerr(SSL_F_SSL_USE_CERTIFICATE_ASN1,ERR_R_ASN1_LIB); | |
147 | return(0); | |
148 | } | |
149 | ||
150 | ret=SSL_use_certificate(ssl,x); | |
151 | X509_free(x); | |
152 | return(ret); | |
153 | } | |
154 | ||
bc36ee62 | 155 | #ifndef OPENSSL_NO_RSA |
6b691a5c | 156 | int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) |
d02b48c6 | 157 | { |
d02b48c6 RE |
158 | EVP_PKEY *pkey; |
159 | int ret; | |
160 | ||
161 | if (rsa == NULL) | |
162 | { | |
163 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); | |
164 | return(0); | |
165 | } | |
ca8e5b9b | 166 | if (!ssl_cert_inst(&ssl->cert)) |
15d21c2d RE |
167 | { |
168 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE); | |
169 | return(0); | |
d02b48c6 | 170 | } |
d02b48c6 RE |
171 | if ((pkey=EVP_PKEY_new()) == NULL) |
172 | { | |
173 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB); | |
174 | return(0); | |
175 | } | |
176 | ||
6ac4e8bd | 177 | RSA_up_ref(rsa); |
d02b48c6 RE |
178 | EVP_PKEY_assign_RSA(pkey,rsa); |
179 | ||
15d21c2d | 180 | ret=ssl_set_pkey(ssl->cert,pkey); |
d02b48c6 RE |
181 | EVP_PKEY_free(pkey); |
182 | return(ret); | |
183 | } | |
184 | #endif | |
185 | ||
6b691a5c | 186 | static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) |
d02b48c6 | 187 | { |
6049399b | 188 | int i; |
0ffa4997 DSH |
189 | /* Special case for DH: check two DH certificate types for a match. |
190 | * This means for DH certificates we must set the certificate first. | |
191 | */ | |
192 | if (pkey->type == EVP_PKEY_DH) | |
193 | { | |
194 | X509 *x; | |
195 | i = -1; | |
196 | x = c->pkeys[SSL_PKEY_DH_RSA].x509; | |
197 | if (x && X509_check_private_key(x, pkey)) | |
198 | i = SSL_PKEY_DH_RSA; | |
199 | x = c->pkeys[SSL_PKEY_DH_DSA].x509; | |
200 | if (i == -1 && x && X509_check_private_key(x, pkey)) | |
201 | i = SSL_PKEY_DH_DSA; | |
202 | ERR_clear_error(); | |
203 | } | |
204 | else | |
205 | i=ssl_cert_type(NULL,pkey); | |
d02b48c6 RE |
206 | if (i < 0) |
207 | { | |
208 | SSLerr(SSL_F_SSL_SET_PKEY,SSL_R_UNKNOWN_CERTIFICATE_TYPE); | |
209 | return(0); | |
210 | } | |
211 | ||
212 | if (c->pkeys[i].x509 != NULL) | |
213 | { | |
a8236c8c DSH |
214 | EVP_PKEY *pktmp; |
215 | pktmp = X509_get_pubkey(c->pkeys[i].x509); | |
216 | EVP_PKEY_copy_parameters(pktmp,pkey); | |
217 | EVP_PKEY_free(pktmp); | |
dfeab068 RE |
218 | ERR_clear_error(); |
219 | ||
bc36ee62 | 220 | #ifndef OPENSSL_NO_RSA |
58964a49 RE |
221 | /* Don't check the public/private key, this is mostly |
222 | * for smart cards. */ | |
223 | if ((pkey->type == EVP_PKEY_RSA) && | |
6049399b NL |
224 | (RSA_flags(pkey->pkey.rsa) & RSA_METHOD_FLAG_NO_CHECK)) |
225 | ; | |
58964a49 RE |
226 | else |
227 | #endif | |
6049399b | 228 | if (!X509_check_private_key(c->pkeys[i].x509,pkey)) |
d02b48c6 | 229 | { |
6049399b NL |
230 | X509_free(c->pkeys[i].x509); |
231 | c->pkeys[i].x509 = NULL; | |
232 | return 0; | |
d02b48c6 | 233 | } |
d02b48c6 RE |
234 | } |
235 | ||
236 | if (c->pkeys[i].privatekey != NULL) | |
237 | EVP_PKEY_free(c->pkeys[i].privatekey); | |
238 | CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY); | |
239 | c->pkeys[i].privatekey=pkey; | |
240 | c->key= &(c->pkeys[i]); | |
241 | ||
242 | c->valid=0; | |
243 | return(1); | |
244 | } | |
245 | ||
bc36ee62 RL |
246 | #ifndef OPENSSL_NO_RSA |
247 | #ifndef OPENSSL_NO_STDIO | |
303c0028 | 248 | int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) |
d02b48c6 RE |
249 | { |
250 | int j,ret=0; | |
251 | BIO *in; | |
252 | RSA *rsa=NULL; | |
253 | ||
58964a49 | 254 | in=BIO_new(BIO_s_file_internal()); |
d02b48c6 RE |
255 | if (in == NULL) |
256 | { | |
257 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,ERR_R_BUF_LIB); | |
258 | goto end; | |
259 | } | |
260 | ||
261 | if (BIO_read_filename(in,file) <= 0) | |
262 | { | |
d02b48c6 RE |
263 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,ERR_R_SYS_LIB); |
264 | goto end; | |
265 | } | |
266 | if (type == SSL_FILETYPE_ASN1) | |
267 | { | |
268 | j=ERR_R_ASN1_LIB; | |
269 | rsa=d2i_RSAPrivateKey_bio(in,NULL); | |
270 | } | |
271 | else if (type == SSL_FILETYPE_PEM) | |
272 | { | |
273 | j=ERR_R_PEM_LIB; | |
274 | rsa=PEM_read_bio_RSAPrivateKey(in,NULL, | |
74678cc2 | 275 | ssl->ctx->default_passwd_callback,ssl->ctx->default_passwd_callback_userdata); |
d02b48c6 RE |
276 | } |
277 | else | |
278 | { | |
279 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,SSL_R_BAD_SSL_FILETYPE); | |
280 | goto end; | |
281 | } | |
282 | if (rsa == NULL) | |
283 | { | |
284 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE,j); | |
285 | goto end; | |
286 | } | |
287 | ret=SSL_use_RSAPrivateKey(ssl,rsa); | |
288 | RSA_free(rsa); | |
289 | end: | |
290 | if (in != NULL) BIO_free(in); | |
291 | return(ret); | |
292 | } | |
58964a49 | 293 | #endif |
d02b48c6 | 294 | |
6b691a5c | 295 | int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len) |
d02b48c6 RE |
296 | { |
297 | int ret; | |
5e4ca422 | 298 | const unsigned char *p; |
d02b48c6 RE |
299 | RSA *rsa; |
300 | ||
301 | p=d; | |
302 | if ((rsa=d2i_RSAPrivateKey(NULL,&p,(long)len)) == NULL) | |
303 | { | |
304 | SSLerr(SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1,ERR_R_ASN1_LIB); | |
305 | return(0); | |
306 | } | |
307 | ||
308 | ret=SSL_use_RSAPrivateKey(ssl,rsa); | |
309 | RSA_free(rsa); | |
310 | return(ret); | |
311 | } | |
bc36ee62 | 312 | #endif /* !OPENSSL_NO_RSA */ |
d02b48c6 | 313 | |
6b691a5c | 314 | int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) |
d02b48c6 | 315 | { |
d02b48c6 RE |
316 | int ret; |
317 | ||
318 | if (pkey == NULL) | |
319 | { | |
320 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); | |
321 | return(0); | |
322 | } | |
ca8e5b9b | 323 | if (!ssl_cert_inst(&ssl->cert)) |
15d21c2d RE |
324 | { |
325 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE); | |
326 | return(0); | |
d02b48c6 | 327 | } |
15d21c2d | 328 | ret=ssl_set_pkey(ssl->cert,pkey); |
d02b48c6 RE |
329 | return(ret); |
330 | } | |
331 | ||
bc36ee62 | 332 | #ifndef OPENSSL_NO_STDIO |
303c0028 | 333 | int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) |
d02b48c6 RE |
334 | { |
335 | int j,ret=0; | |
336 | BIO *in; | |
337 | EVP_PKEY *pkey=NULL; | |
338 | ||
58964a49 | 339 | in=BIO_new(BIO_s_file_internal()); |
d02b48c6 RE |
340 | if (in == NULL) |
341 | { | |
342 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE,ERR_R_BUF_LIB); | |
343 | goto end; | |
344 | } | |
345 | ||
346 | if (BIO_read_filename(in,file) <= 0) | |
347 | { | |
d02b48c6 RE |
348 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE,ERR_R_SYS_LIB); |
349 | goto end; | |
350 | } | |
351 | if (type == SSL_FILETYPE_PEM) | |
352 | { | |
353 | j=ERR_R_PEM_LIB; | |
354 | pkey=PEM_read_bio_PrivateKey(in,NULL, | |
74678cc2 | 355 | ssl->ctx->default_passwd_callback,ssl->ctx->default_passwd_callback_userdata); |
d02b48c6 | 356 | } |
dc0ed30c NL |
357 | else if (type == SSL_FILETYPE_ASN1) |
358 | { | |
359 | j = ERR_R_ASN1_LIB; | |
360 | pkey = d2i_PrivateKey_bio(in,NULL); | |
361 | } | |
d02b48c6 RE |
362 | else |
363 | { | |
364 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE,SSL_R_BAD_SSL_FILETYPE); | |
365 | goto end; | |
366 | } | |
367 | if (pkey == NULL) | |
368 | { | |
369 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY_FILE,j); | |
370 | goto end; | |
371 | } | |
372 | ret=SSL_use_PrivateKey(ssl,pkey); | |
373 | EVP_PKEY_free(pkey); | |
374 | end: | |
375 | if (in != NULL) BIO_free(in); | |
376 | return(ret); | |
377 | } | |
58964a49 | 378 | #endif |
d02b48c6 | 379 | |
875a644a | 380 | int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d, long len) |
d02b48c6 RE |
381 | { |
382 | int ret; | |
875a644a | 383 | const unsigned char *p; |
d02b48c6 RE |
384 | EVP_PKEY *pkey; |
385 | ||
386 | p=d; | |
387 | if ((pkey=d2i_PrivateKey(type,NULL,&p,(long)len)) == NULL) | |
388 | { | |
389 | SSLerr(SSL_F_SSL_USE_PRIVATEKEY_ASN1,ERR_R_ASN1_LIB); | |
390 | return(0); | |
391 | } | |
392 | ||
393 | ret=SSL_use_PrivateKey(ssl,pkey); | |
394 | EVP_PKEY_free(pkey); | |
395 | return(ret); | |
396 | } | |
397 | ||
6b691a5c | 398 | int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) |
d02b48c6 | 399 | { |
d02b48c6 RE |
400 | if (x == NULL) |
401 | { | |
402 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_PASSED_NULL_PARAMETER); | |
403 | return(0); | |
404 | } | |
ca8e5b9b | 405 | if (!ssl_cert_inst(&ctx->cert)) |
d02b48c6 | 406 | { |
15d21c2d RE |
407 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE,ERR_R_MALLOC_FAILURE); |
408 | return(0); | |
d02b48c6 | 409 | } |
ca8e5b9b | 410 | return(ssl_set_cert(ctx->cert, x)); |
d02b48c6 RE |
411 | } |
412 | ||
6b691a5c | 413 | static int ssl_set_cert(CERT *c, X509 *x) |
d02b48c6 RE |
414 | { |
415 | EVP_PKEY *pkey; | |
6049399b | 416 | int i; |
d02b48c6 RE |
417 | |
418 | pkey=X509_get_pubkey(x); | |
419 | if (pkey == NULL) | |
420 | { | |
58964a49 | 421 | SSLerr(SSL_F_SSL_SET_CERT,SSL_R_X509_LIB); |
d02b48c6 RE |
422 | return(0); |
423 | } | |
424 | ||
425 | i=ssl_cert_type(x,pkey); | |
426 | if (i < 0) | |
427 | { | |
58964a49 | 428 | SSLerr(SSL_F_SSL_SET_CERT,SSL_R_UNKNOWN_CERTIFICATE_TYPE); |
a8236c8c | 429 | EVP_PKEY_free(pkey); |
d02b48c6 RE |
430 | return(0); |
431 | } | |
432 | ||
433 | if (c->pkeys[i].privatekey != NULL) | |
dfeab068 RE |
434 | { |
435 | EVP_PKEY_copy_parameters(pkey,c->pkeys[i].privatekey); | |
436 | ERR_clear_error(); | |
437 | ||
bc36ee62 | 438 | #ifndef OPENSSL_NO_RSA |
dfeab068 RE |
439 | /* Don't check the public/private key, this is mostly |
440 | * for smart cards. */ | |
441 | if ((c->pkeys[i].privatekey->type == EVP_PKEY_RSA) && | |
442 | (RSA_flags(c->pkeys[i].privatekey->pkey.rsa) & | |
443 | RSA_METHOD_FLAG_NO_CHECK)) | |
6049399b | 444 | ; |
dfeab068 | 445 | else |
6049399b | 446 | #endif /* OPENSSL_NO_RSA */ |
d02b48c6 RE |
447 | if (!X509_check_private_key(x,c->pkeys[i].privatekey)) |
448 | { | |
6049399b NL |
449 | /* don't fail for a cert/key mismatch, just free |
450 | * current private key (when switching to a different | |
451 | * cert & key, first this function should be used, | |
452 | * then ssl_set_pkey */ | |
453 | EVP_PKEY_free(c->pkeys[i].privatekey); | |
454 | c->pkeys[i].privatekey=NULL; | |
455 | /* clear error queue */ | |
456 | ERR_clear_error(); | |
d02b48c6 | 457 | } |
d02b48c6 | 458 | } |
d02b48c6 | 459 | |
a8236c8c | 460 | EVP_PKEY_free(pkey); |
d02b48c6 RE |
461 | |
462 | if (c->pkeys[i].x509 != NULL) | |
463 | X509_free(c->pkeys[i].x509); | |
464 | CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509); | |
465 | c->pkeys[i].x509=x; | |
8a02a46a BL |
466 | #ifndef OPENSSL_NO_TLSEXT |
467 | /* Free the old authz data, if it exists. */ | |
468 | if (c->pkeys[i].authz != NULL) | |
469 | { | |
470 | OPENSSL_free(c->pkeys[i].authz); | |
471 | c->pkeys[i].authz = NULL; | |
472 | c->pkeys[i].authz_length = 0; | |
473 | } | |
e27711cf T |
474 | |
475 | /* Free the old serverinfo data, if it exists. */ | |
476 | if (c->pkeys[i].serverinfo != NULL) | |
477 | { | |
478 | OPENSSL_free(c->pkeys[i].serverinfo); | |
479 | c->pkeys[i].serverinfo = NULL; | |
480 | c->pkeys[i].serverinfo_length = 0; | |
481 | } | |
8a02a46a | 482 | #endif |
d02b48c6 RE |
483 | c->key= &(c->pkeys[i]); |
484 | ||
485 | c->valid=0; | |
486 | return(1); | |
487 | } | |
488 | ||
bc36ee62 | 489 | #ifndef OPENSSL_NO_STDIO |
303c0028 | 490 | int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) |
d02b48c6 RE |
491 | { |
492 | int j; | |
493 | BIO *in; | |
494 | int ret=0; | |
495 | X509 *x=NULL; | |
496 | ||
58964a49 | 497 | in=BIO_new(BIO_s_file_internal()); |
d02b48c6 RE |
498 | if (in == NULL) |
499 | { | |
500 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,ERR_R_BUF_LIB); | |
501 | goto end; | |
502 | } | |
503 | ||
504 | if (BIO_read_filename(in,file) <= 0) | |
505 | { | |
d02b48c6 RE |
506 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,ERR_R_SYS_LIB); |
507 | goto end; | |
508 | } | |
509 | if (type == SSL_FILETYPE_ASN1) | |
510 | { | |
511 | j=ERR_R_ASN1_LIB; | |
512 | x=d2i_X509_bio(in,NULL); | |
513 | } | |
514 | else if (type == SSL_FILETYPE_PEM) | |
515 | { | |
516 | j=ERR_R_PEM_LIB; | |
74678cc2 | 517 | x=PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata); |
d02b48c6 RE |
518 | } |
519 | else | |
520 | { | |
521 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,SSL_R_BAD_SSL_FILETYPE); | |
522 | goto end; | |
523 | } | |
524 | ||
525 | if (x == NULL) | |
526 | { | |
527 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,j); | |
528 | goto end; | |
529 | } | |
530 | ||
531 | ret=SSL_CTX_use_certificate(ctx,x); | |
532 | end: | |
533 | if (x != NULL) X509_free(x); | |
534 | if (in != NULL) BIO_free(in); | |
535 | return(ret); | |
536 | } | |
58964a49 | 537 | #endif |
d02b48c6 | 538 | |
875a644a | 539 | int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d) |
d02b48c6 RE |
540 | { |
541 | X509 *x; | |
542 | int ret; | |
543 | ||
544 | x=d2i_X509(NULL,&d,(long)len); | |
545 | if (x == NULL) | |
546 | { | |
547 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1,ERR_R_ASN1_LIB); | |
548 | return(0); | |
549 | } | |
550 | ||
551 | ret=SSL_CTX_use_certificate(ctx,x); | |
552 | X509_free(x); | |
553 | return(ret); | |
554 | } | |
555 | ||
bc36ee62 | 556 | #ifndef OPENSSL_NO_RSA |
6b691a5c | 557 | int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) |
d02b48c6 RE |
558 | { |
559 | int ret; | |
d02b48c6 RE |
560 | EVP_PKEY *pkey; |
561 | ||
562 | if (rsa == NULL) | |
563 | { | |
564 | SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); | |
565 | return(0); | |
566 | } | |
ca8e5b9b | 567 | if (!ssl_cert_inst(&ctx->cert)) |
d02b48c6 | 568 | { |
15d21c2d RE |
569 | SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_MALLOC_FAILURE); |
570 | return(0); | |
d02b48c6 | 571 | } |
d02b48c6 RE |
572 | if ((pkey=EVP_PKEY_new()) == NULL) |
573 | { | |
574 | SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY,ERR_R_EVP_LIB); | |
575 | return(0); | |
576 | } | |
577 | ||
6ac4e8bd | 578 | RSA_up_ref(rsa); |
d02b48c6 RE |
579 | EVP_PKEY_assign_RSA(pkey,rsa); |
580 | ||
ca8e5b9b | 581 | ret=ssl_set_pkey(ctx->cert, pkey); |
d02b48c6 RE |
582 | EVP_PKEY_free(pkey); |
583 | return(ret); | |
584 | } | |
585 | ||
bc36ee62 | 586 | #ifndef OPENSSL_NO_STDIO |
303c0028 | 587 | int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) |
d02b48c6 RE |
588 | { |
589 | int j,ret=0; | |
590 | BIO *in; | |
591 | RSA *rsa=NULL; | |
592 | ||
58964a49 | 593 | in=BIO_new(BIO_s_file_internal()); |
d02b48c6 RE |
594 | if (in == NULL) |
595 | { | |
596 | SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,ERR_R_BUF_LIB); | |
597 | goto end; | |
598 | } | |
599 | ||
600 | if (BIO_read_filename(in,file) <= 0) | |
601 | { | |
d02b48c6 RE |
602 | SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,ERR_R_SYS_LIB); |
603 | goto end; | |
604 | } | |
605 | if (type == SSL_FILETYPE_ASN1) | |
606 | { | |
607 | j=ERR_R_ASN1_LIB; | |
608 | rsa=d2i_RSAPrivateKey_bio(in,NULL); | |
609 | } | |
610 | else if (type == SSL_FILETYPE_PEM) | |
611 | { | |
612 | j=ERR_R_PEM_LIB; | |
613 | rsa=PEM_read_bio_RSAPrivateKey(in,NULL, | |
74678cc2 | 614 | ctx->default_passwd_callback,ctx->default_passwd_callback_userdata); |
d02b48c6 RE |
615 | } |
616 | else | |
617 | { | |
618 | SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,SSL_R_BAD_SSL_FILETYPE); | |
619 | goto end; | |
620 | } | |
621 | if (rsa == NULL) | |
622 | { | |
623 | SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE,j); | |
624 | goto end; | |
625 | } | |
626 | ret=SSL_CTX_use_RSAPrivateKey(ctx,rsa); | |
627 | RSA_free(rsa); | |
628 | end: | |
629 | if (in != NULL) BIO_free(in); | |
630 | return(ret); | |
631 | } | |
58964a49 | 632 | #endif |
d02b48c6 | 633 | |
875a644a | 634 | int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len) |
d02b48c6 RE |
635 | { |
636 | int ret; | |
5e4ca422 | 637 | const unsigned char *p; |
d02b48c6 RE |
638 | RSA *rsa; |
639 | ||
640 | p=d; | |
641 | if ((rsa=d2i_RSAPrivateKey(NULL,&p,(long)len)) == NULL) | |
642 | { | |
643 | SSLerr(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1,ERR_R_ASN1_LIB); | |
644 | return(0); | |
645 | } | |
646 | ||
647 | ret=SSL_CTX_use_RSAPrivateKey(ctx,rsa); | |
648 | RSA_free(rsa); | |
649 | return(ret); | |
650 | } | |
bc36ee62 | 651 | #endif /* !OPENSSL_NO_RSA */ |
d02b48c6 | 652 | |
6b691a5c | 653 | int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) |
d02b48c6 | 654 | { |
d02b48c6 RE |
655 | if (pkey == NULL) |
656 | { | |
657 | SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_PASSED_NULL_PARAMETER); | |
658 | return(0); | |
659 | } | |
ca8e5b9b | 660 | if (!ssl_cert_inst(&ctx->cert)) |
d02b48c6 | 661 | { |
15d21c2d RE |
662 | SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY,ERR_R_MALLOC_FAILURE); |
663 | return(0); | |
d02b48c6 | 664 | } |
ca8e5b9b | 665 | return(ssl_set_pkey(ctx->cert,pkey)); |
d02b48c6 RE |
666 | } |
667 | ||
bc36ee62 | 668 | #ifndef OPENSSL_NO_STDIO |
303c0028 | 669 | int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) |
d02b48c6 RE |
670 | { |
671 | int j,ret=0; | |
672 | BIO *in; | |
673 | EVP_PKEY *pkey=NULL; | |
674 | ||
58964a49 | 675 | in=BIO_new(BIO_s_file_internal()); |
d02b48c6 RE |
676 | if (in == NULL) |
677 | { | |
678 | SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,ERR_R_BUF_LIB); | |
679 | goto end; | |
680 | } | |
681 | ||
682 | if (BIO_read_filename(in,file) <= 0) | |
683 | { | |
d02b48c6 RE |
684 | SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,ERR_R_SYS_LIB); |
685 | goto end; | |
686 | } | |
687 | if (type == SSL_FILETYPE_PEM) | |
688 | { | |
689 | j=ERR_R_PEM_LIB; | |
690 | pkey=PEM_read_bio_PrivateKey(in,NULL, | |
74678cc2 | 691 | ctx->default_passwd_callback,ctx->default_passwd_callback_userdata); |
d02b48c6 | 692 | } |
dc0ed30c NL |
693 | else if (type == SSL_FILETYPE_ASN1) |
694 | { | |
695 | j = ERR_R_ASN1_LIB; | |
696 | pkey = d2i_PrivateKey_bio(in,NULL); | |
697 | } | |
d02b48c6 RE |
698 | else |
699 | { | |
700 | SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,SSL_R_BAD_SSL_FILETYPE); | |
701 | goto end; | |
702 | } | |
703 | if (pkey == NULL) | |
704 | { | |
705 | SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE,j); | |
706 | goto end; | |
707 | } | |
708 | ret=SSL_CTX_use_PrivateKey(ctx,pkey); | |
709 | EVP_PKEY_free(pkey); | |
710 | end: | |
711 | if (in != NULL) BIO_free(in); | |
712 | return(ret); | |
713 | } | |
58964a49 | 714 | #endif |
d02b48c6 | 715 | |
875a644a | 716 | int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const unsigned char *d, |
6b691a5c | 717 | long len) |
d02b48c6 RE |
718 | { |
719 | int ret; | |
875a644a | 720 | const unsigned char *p; |
d02b48c6 RE |
721 | EVP_PKEY *pkey; |
722 | ||
723 | p=d; | |
724 | if ((pkey=d2i_PrivateKey(type,NULL,&p,(long)len)) == NULL) | |
725 | { | |
726 | SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1,ERR_R_ASN1_LIB); | |
727 | return(0); | |
728 | } | |
729 | ||
730 | ret=SSL_CTX_use_PrivateKey(ctx,pkey); | |
731 | EVP_PKEY_free(pkey); | |
732 | return(ret); | |
733 | } | |
734 | ||
735 | ||
bc36ee62 | 736 | #ifndef OPENSSL_NO_STDIO |
b3ca645f BM |
737 | /* Read a file that contains our certificate in "PEM" format, |
738 | * possibly followed by a sequence of CA certificates that should be | |
739 | * sent to the peer in the Certificate message. | |
740 | */ | |
741 | int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) | |
742 | { | |
743 | BIO *in; | |
744 | int ret=0; | |
745 | X509 *x=NULL; | |
746 | ||
17a4a4df | 747 | ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */ |
c2c2e7a4 | 748 | |
8a02a46a | 749 | in = BIO_new(BIO_s_file_internal()); |
b3ca645f BM |
750 | if (in == NULL) |
751 | { | |
752 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_BUF_LIB); | |
753 | goto end; | |
754 | } | |
755 | ||
756 | if (BIO_read_filename(in,file) <= 0) | |
757 | { | |
758 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_SYS_LIB); | |
759 | goto end; | |
760 | } | |
761 | ||
8a02a46a BL |
762 | x=PEM_read_bio_X509_AUX(in,NULL,ctx->default_passwd_callback, |
763 | ctx->default_passwd_callback_userdata); | |
b3ca645f BM |
764 | if (x == NULL) |
765 | { | |
766 | SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE,ERR_R_PEM_LIB); | |
767 | goto end; | |
768 | } | |
769 | ||
8a02a46a BL |
770 | ret = SSL_CTX_use_certificate(ctx, x); |
771 | ||
b3ca645f BM |
772 | if (ERR_peek_error() != 0) |
773 | ret = 0; /* Key/certificate mismatch doesn't imply ret==0 ... */ | |
774 | if (ret) | |
775 | { | |
776 | /* If we could set up our certificate, now proceed to | |
777 | * the CA certificates. | |
778 | */ | |
779 | X509 *ca; | |
780 | int r; | |
781 | unsigned long err; | |
782 | ||
8a02a46a | 783 | if (ctx->extra_certs != NULL) |
b3ca645f BM |
784 | { |
785 | sk_X509_pop_free(ctx->extra_certs, X509_free); | |
786 | ctx->extra_certs = NULL; | |
787 | } | |
788 | ||
8a02a46a BL |
789 | while ((ca = PEM_read_bio_X509(in, NULL, |
790 | ctx->default_passwd_callback, | |
791 | ctx->default_passwd_callback_userdata)) | |
b3ca645f BM |
792 | != NULL) |
793 | { | |
794 | r = SSL_CTX_add_extra_chain_cert(ctx, ca); | |
795 | if (!r) | |
796 | { | |
797 | X509_free(ca); | |
798 | ret = 0; | |
799 | goto end; | |
800 | } | |
b1816a04 | 801 | /* Note that we must not free r if it was successfully |
b3ca645f BM |
802 | * added to the chain (while we must free the main |
803 | * certificate, since its reference count is increased | |
804 | * by SSL_CTX_use_certificate). */ | |
805 | } | |
806 | /* When the while loop ends, it's usually just EOF. */ | |
9437fef8 | 807 | err = ERR_peek_last_error(); |
b3ca645f | 808 | if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) |
48c832b6 | 809 | ERR_clear_error(); |
b3ca645f BM |
810 | else |
811 | ret = 0; /* some real error */ | |
812 | } | |
813 | ||
814 | end: | |
815 | if (x != NULL) X509_free(x); | |
816 | if (in != NULL) BIO_free(in); | |
817 | return(ret); | |
818 | } | |
819 | #endif | |
8a02a46a BL |
820 | |
821 | #ifndef OPENSSL_NO_TLSEXT | |
822 | /* authz_validate returns true iff authz is well formed, i.e. that it meets the | |
823 | * wire format as documented in the CERT_PKEY structure and that there are no | |
824 | * duplicate entries. */ | |
825 | static char authz_validate(const unsigned char *authz, size_t length) | |
826 | { | |
827 | unsigned char types_seen_bitmap[32]; | |
828 | ||
829 | if (!authz) | |
830 | return 1; | |
831 | ||
832 | memset(types_seen_bitmap, 0, sizeof(types_seen_bitmap)); | |
833 | ||
834 | for (;;) | |
835 | { | |
836 | unsigned char type, byte, bit; | |
837 | unsigned short len; | |
838 | ||
839 | if (!length) | |
840 | return 1; | |
841 | ||
842 | type = *(authz++); | |
843 | length--; | |
844 | ||
845 | byte = type / 8; | |
846 | bit = type & 7; | |
847 | if (types_seen_bitmap[byte] & (1 << bit)) | |
848 | return 0; | |
849 | types_seen_bitmap[byte] |= (1 << bit); | |
850 | ||
851 | if (length < 2) | |
852 | return 0; | |
853 | len = ((unsigned short) authz[0]) << 8 | | |
854 | ((unsigned short) authz[1]); | |
855 | authz += 2; | |
856 | length -= 2; | |
857 | ||
858 | if (length < len) | |
859 | return 0; | |
860 | ||
861 | authz += len; | |
862 | length -= len; | |
863 | } | |
864 | } | |
865 | ||
e27711cf T |
866 | static int serverinfo_find_extension(const unsigned char *serverinfo, |
867 | size_t serverinfo_length, | |
868 | unsigned short extension_type, | |
869 | const unsigned char **extension_data, | |
870 | unsigned short *extension_length) | |
871 | { | |
872 | *extension_data = NULL; | |
873 | *extension_length = 0; | |
874 | if (serverinfo == NULL || serverinfo_length == 0) | |
875 | return 0; | |
876 | for (;;) | |
877 | { | |
878 | unsigned short type = 0; /* uint16 */ | |
879 | unsigned short len = 0; /* uint16 */ | |
880 | ||
881 | /* end of serverinfo */ | |
882 | if (serverinfo_length == 0) | |
883 | return -1; /* Extension not found */ | |
884 | ||
885 | /* read 2-byte type field */ | |
886 | if (serverinfo_length < 2) | |
887 | return 0; /* Error */ | |
888 | type = (serverinfo[0] << 8) + serverinfo[1]; | |
889 | serverinfo += 2; | |
890 | serverinfo_length -= 2; | |
891 | ||
892 | /* read 2-byte len field */ | |
893 | if (serverinfo_length < 2) | |
894 | return 0; /* Error */ | |
895 | len = (serverinfo[0] << 8) + serverinfo[1]; | |
896 | serverinfo += 2; | |
897 | serverinfo_length -= 2; | |
898 | ||
899 | if (len > serverinfo_length) | |
900 | return 0; /* Error */ | |
901 | ||
902 | if (type == extension_type) | |
903 | { | |
904 | *extension_data = serverinfo; | |
905 | *extension_length = len; | |
906 | return 1; /* Success */ | |
907 | } | |
908 | ||
909 | serverinfo += len; | |
910 | serverinfo_length -= len; | |
911 | } | |
912 | return 0; /* Error */ | |
913 | } | |
914 | ||
915 | static int serverinfo_srv_first_cb(SSL *s, unsigned short ext_type, | |
916 | const unsigned char *in, | |
917 | unsigned short inlen, int *al, | |
918 | void *arg) | |
919 | { | |
920 | if (inlen != 0) | |
921 | { | |
922 | *al = SSL_AD_DECODE_ERROR; | |
923 | return 0; | |
924 | } | |
925 | return 1; | |
926 | } | |
927 | ||
928 | static int serverinfo_srv_second_cb(SSL *s, unsigned short ext_type, | |
929 | const unsigned char **out, unsigned short *outlen, | |
930 | void *arg) | |
931 | { | |
932 | const unsigned char *serverinfo = NULL; | |
933 | size_t serverinfo_length = 0; | |
934 | ||
935 | /* Is there serverinfo data for the chosen server cert? */ | |
936 | if ((ssl_get_server_cert_serverinfo(s, &serverinfo, | |
937 | &serverinfo_length)) != 0) | |
938 | { | |
939 | /* Find the relevant extension from the serverinfo */ | |
940 | int retval = serverinfo_find_extension(serverinfo, serverinfo_length, | |
941 | ext_type, out, outlen); | |
942 | if (retval == 0) | |
943 | return 0; /* Error */ | |
944 | if (retval == -1) | |
945 | return -1; /* No extension found, don't send extension */ | |
946 | return 1; /* Send extension */ | |
947 | } | |
948 | return -1; /* No serverinfo data found, don't send extension */ | |
949 | } | |
950 | ||
951 | /* With a NULL context, this function just checks that the serverinfo data | |
952 | parses correctly. With a non-NULL context, it registers callbacks for | |
953 | the included extensions. */ | |
954 | static int serverinfo_process_buffer(const unsigned char *serverinfo, | |
955 | size_t serverinfo_length, SSL_CTX *ctx) | |
956 | { | |
957 | if (serverinfo == NULL || serverinfo_length == 0) | |
958 | return 0; | |
959 | for (;;) | |
960 | { | |
961 | unsigned short ext_type = 0; /* uint16 */ | |
962 | unsigned short len = 0; /* uint16 */ | |
963 | ||
964 | /* end of serverinfo */ | |
965 | if (serverinfo_length == 0) | |
966 | return 1; | |
967 | ||
968 | /* read 2-byte type field */ | |
969 | if (serverinfo_length < 2) | |
970 | return 0; | |
971 | /* FIXME: check for types we understand explicitly? */ | |
972 | ||
973 | /* Register callbacks for extensions */ | |
974 | ext_type = (serverinfo[0] << 8) + serverinfo[1]; | |
975 | if (ctx && !SSL_CTX_set_custom_srv_ext(ctx, ext_type, | |
976 | serverinfo_srv_first_cb, | |
977 | serverinfo_srv_second_cb, NULL)) | |
978 | return 0; | |
979 | ||
980 | serverinfo += 2; | |
981 | serverinfo_length -= 2; | |
982 | ||
983 | /* read 2-byte len field */ | |
984 | if (serverinfo_length < 2) | |
985 | return 0; | |
986 | len = (serverinfo[0] << 8) + serverinfo[1]; | |
987 | serverinfo += 2; | |
988 | serverinfo_length -= 2; | |
989 | ||
990 | if (len > serverinfo_length) | |
991 | return 0; | |
992 | ||
993 | serverinfo += len; | |
994 | serverinfo_length -= len; | |
995 | } | |
996 | } | |
997 | ||
835d104f BL |
998 | static const unsigned char *authz_find_data(const unsigned char *authz, |
999 | size_t authz_length, | |
1000 | unsigned char data_type, | |
1001 | size_t *data_length) | |
1002 | { | |
1003 | if (authz == NULL) return NULL; | |
1004 | if (!authz_validate(authz, authz_length)) | |
1005 | { | |
1006 | SSLerr(SSL_F_AUTHZ_FIND_DATA,SSL_R_INVALID_AUTHZ_DATA); | |
1007 | return NULL; | |
1008 | } | |
1009 | ||
1010 | for (;;) | |
1011 | { | |
1012 | unsigned char type; | |
1013 | unsigned short len; | |
1014 | if (!authz_length) | |
1015 | return NULL; | |
1016 | ||
1017 | type = *(authz++); | |
1018 | authz_length--; | |
1019 | ||
1020 | /* We've validated the authz data, so we don't have to | |
1021 | * check again that we have enough bytes left. */ | |
1022 | len = ((unsigned short) authz[0]) << 8 | | |
1023 | ((unsigned short) authz[1]); | |
1024 | authz += 2; | |
1025 | authz_length -= 2; | |
1026 | if (type == data_type) | |
1027 | { | |
1028 | *data_length = len; | |
1029 | return authz; | |
1030 | } | |
1031 | authz += len; | |
1032 | authz_length -= len; | |
1033 | } | |
1034 | /* No match */ | |
1035 | return NULL; | |
1036 | } | |
1037 | ||
8a02a46a BL |
1038 | static int ssl_set_authz(CERT *c, unsigned char *authz, size_t authz_length) |
1039 | { | |
1040 | CERT_PKEY *current_key = c->key; | |
1041 | if (current_key == NULL) | |
1042 | return 0; | |
1043 | if (!authz_validate(authz, authz_length)) | |
1044 | { | |
1045 | SSLerr(SSL_F_SSL_SET_AUTHZ,SSL_R_INVALID_AUTHZ_DATA); | |
1046 | return(0); | |
1047 | } | |
1048 | current_key->authz = OPENSSL_realloc(current_key->authz, authz_length); | |
e27711cf T |
1049 | if (current_key->authz == NULL) |
1050 | { | |
1051 | SSLerr(SSL_F_SSL_SET_AUTHZ,ERR_R_MALLOC_FAILURE); | |
1052 | return 0; | |
1053 | } | |
8a02a46a BL |
1054 | current_key->authz_length = authz_length; |
1055 | memcpy(current_key->authz, authz, authz_length); | |
1056 | return 1; | |
1057 | } | |
1058 | ||
1059 | int SSL_CTX_use_authz(SSL_CTX *ctx, unsigned char *authz, | |
e27711cf | 1060 | size_t authz_length) |
8a02a46a BL |
1061 | { |
1062 | if (authz == NULL) | |
1063 | { | |
1064 | SSLerr(SSL_F_SSL_CTX_USE_AUTHZ,ERR_R_PASSED_NULL_PARAMETER); | |
1065 | return 0; | |
1066 | } | |
1067 | if (!ssl_cert_inst(&ctx->cert)) | |
1068 | { | |
1069 | SSLerr(SSL_F_SSL_CTX_USE_AUTHZ,ERR_R_MALLOC_FAILURE); | |
1070 | return 0; | |
1071 | } | |
1072 | return ssl_set_authz(ctx->cert, authz, authz_length); | |
1073 | } | |
1074 | ||
e27711cf T |
1075 | int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo, |
1076 | size_t serverinfo_length) | |
1077 | { | |
1078 | if (ctx == NULL || serverinfo == NULL || serverinfo_length == 0) | |
1079 | { | |
1080 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO,ERR_R_PASSED_NULL_PARAMETER); | |
1081 | return 0; | |
1082 | } | |
1083 | if (!serverinfo_process_buffer(serverinfo, serverinfo_length, NULL)) | |
1084 | { | |
1085 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO,SSL_R_INVALID_SERVERINFO_DATA); | |
1086 | return(0); | |
1087 | } | |
1088 | if (!ssl_cert_inst(&ctx->cert)) | |
1089 | { | |
1090 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO,ERR_R_MALLOC_FAILURE); | |
1091 | return 0; | |
1092 | } | |
1093 | if (ctx->cert->key == NULL) | |
1094 | { | |
1095 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO,ERR_R_INTERNAL_ERROR); | |
1096 | return 0; | |
1097 | } | |
1098 | ctx->cert->key->serverinfo = OPENSSL_realloc(ctx->cert->key->serverinfo, | |
1099 | serverinfo_length); | |
1100 | if (ctx->cert->key->serverinfo == NULL) | |
1101 | { | |
1102 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO,ERR_R_MALLOC_FAILURE); | |
1103 | return 0; | |
1104 | } | |
1105 | memcpy(ctx->cert->key->serverinfo, serverinfo, serverinfo_length); | |
1106 | ctx->cert->key->serverinfo_length = serverinfo_length; | |
1107 | ||
1108 | /* Now that the serverinfo is validated and stored, go ahead and | |
1109 | * register callbacks. */ | |
1110 | if (!serverinfo_process_buffer(serverinfo, serverinfo_length, ctx)) | |
1111 | { | |
1112 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO,SSL_R_INVALID_SERVERINFO_DATA); | |
1113 | return(0); | |
1114 | } | |
1115 | return 1; | |
1116 | } | |
1117 | ||
8a02a46a BL |
1118 | int SSL_use_authz(SSL *ssl, unsigned char *authz, size_t authz_length) |
1119 | { | |
1120 | if (authz == NULL) | |
1121 | { | |
1122 | SSLerr(SSL_F_SSL_USE_AUTHZ,ERR_R_PASSED_NULL_PARAMETER); | |
1123 | return 0; | |
1124 | } | |
1125 | if (!ssl_cert_inst(&ssl->cert)) | |
1126 | { | |
1127 | SSLerr(SSL_F_SSL_USE_AUTHZ,ERR_R_MALLOC_FAILURE); | |
1128 | return 0; | |
1129 | } | |
1130 | return ssl_set_authz(ssl->cert, authz, authz_length); | |
1131 | } | |
835d104f BL |
1132 | |
1133 | const unsigned char *SSL_CTX_get_authz_data(SSL_CTX *ctx, unsigned char type, | |
1134 | size_t *data_length) | |
1135 | { | |
1136 | CERT_PKEY *current_key; | |
1137 | ||
1138 | if (ctx->cert == NULL) | |
1139 | return NULL; | |
1140 | current_key = ctx->cert->key; | |
1141 | if (current_key->authz == NULL) | |
1142 | return NULL; | |
1143 | return authz_find_data(current_key->authz, | |
1144 | current_key->authz_length, type, data_length); | |
1145 | } | |
1146 | ||
1147 | #ifndef OPENSSL_NO_STDIO | |
1148 | /* read_authz returns a newly allocated buffer with authz data */ | |
1149 | static unsigned char *read_authz(const char *file, size_t *authz_length) | |
1150 | { | |
1151 | BIO *authz_in = NULL; | |
1152 | unsigned char *authz = NULL; | |
1153 | /* Allow authzs up to 64KB. */ | |
1154 | static const size_t authz_limit = 65536; | |
1155 | size_t read_length; | |
1156 | unsigned char *ret = NULL; | |
1157 | ||
1158 | authz_in = BIO_new(BIO_s_file_internal()); | |
1159 | if (authz_in == NULL) | |
1160 | { | |
1161 | SSLerr(SSL_F_READ_AUTHZ,ERR_R_BUF_LIB); | |
1162 | goto end; | |
1163 | } | |
1164 | ||
1165 | if (BIO_read_filename(authz_in,file) <= 0) | |
1166 | { | |
1167 | SSLerr(SSL_F_READ_AUTHZ,ERR_R_SYS_LIB); | |
1168 | goto end; | |
1169 | } | |
1170 | ||
1171 | authz = OPENSSL_malloc(authz_limit); | |
1172 | read_length = BIO_read(authz_in, authz, authz_limit); | |
1173 | if (read_length == authz_limit || read_length <= 0) | |
1174 | { | |
1175 | SSLerr(SSL_F_READ_AUTHZ,SSL_R_AUTHZ_DATA_TOO_LARGE); | |
1176 | OPENSSL_free(authz); | |
1177 | goto end; | |
1178 | } | |
1179 | *authz_length = read_length; | |
1180 | ret = authz; | |
1181 | end: | |
1182 | if (authz_in != NULL) BIO_free(authz_in); | |
1183 | return ret; | |
1184 | } | |
1185 | ||
1186 | int SSL_CTX_use_authz_file(SSL_CTX *ctx, const char *file) | |
1187 | { | |
1188 | unsigned char *authz = NULL; | |
1189 | size_t authz_length = 0; | |
1190 | int ret; | |
1191 | ||
1192 | authz = read_authz(file, &authz_length); | |
1193 | if (authz == NULL) | |
1194 | return 0; | |
1195 | ||
1196 | ret = SSL_CTX_use_authz(ctx, authz, authz_length); | |
1197 | /* SSL_CTX_use_authz makes a local copy of the authz. */ | |
1198 | OPENSSL_free(authz); | |
1199 | return ret; | |
1200 | } | |
1201 | ||
1202 | int SSL_use_authz_file(SSL *ssl, const char *file) | |
1203 | { | |
1204 | unsigned char *authz = NULL; | |
1205 | size_t authz_length = 0; | |
1206 | int ret; | |
1207 | ||
1208 | authz = read_authz(file, &authz_length); | |
1209 | if (authz == NULL) | |
1210 | return 0; | |
1211 | ||
1212 | ret = SSL_use_authz(ssl, authz, authz_length); | |
1213 | /* SSL_use_authz makes a local copy of the authz. */ | |
1214 | OPENSSL_free(authz); | |
1215 | return ret; | |
1216 | } | |
e27711cf T |
1217 | |
1218 | int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file) | |
1219 | { | |
1220 | unsigned char *serverinfo = NULL; | |
1221 | size_t serverinfo_length = 0; | |
1222 | unsigned char* extension = 0; | |
1223 | long extension_length = 0; | |
1224 | char* name = NULL; | |
1225 | char* header = NULL; | |
1226 | int ret = 0; | |
1227 | BIO *bin = NULL; | |
1228 | size_t num_extensions = 0; | |
1229 | ||
1230 | if (ctx == NULL || file == NULL) | |
1231 | { | |
1232 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE,ERR_R_PASSED_NULL_PARAMETER); | |
1233 | goto end; | |
1234 | } | |
1235 | ||
1236 | bin = BIO_new(BIO_s_file_internal()); | |
1237 | if (bin == NULL) | |
1238 | { | |
1239 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_BUF_LIB); | |
1240 | goto end; | |
1241 | } | |
1242 | if (BIO_read_filename(bin, file) <= 0) | |
1243 | { | |
1244 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_SYS_LIB); | |
1245 | goto end; | |
1246 | } | |
1247 | ||
1248 | for (num_extensions=0;; num_extensions++) | |
1249 | { | |
1250 | if (PEM_read_bio(bin, &name, &header, &extension, &extension_length) == 0) | |
1251 | { | |
1252 | /* There must be at least one extension in this file */ | |
1253 | if (num_extensions == 0) | |
1254 | { | |
1255 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_PEM_LIB); | |
1256 | goto end; | |
1257 | } | |
1258 | else /* End of file, we're done */ | |
1259 | break; | |
1260 | } | |
1261 | /* Check that the decoded PEM data is plausible (valid length field) */ | |
1262 | if (extension_length < 4 || (extension[2] << 8) + extension[3] != extension_length - 4) | |
1263 | { | |
1264 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_PEM_LIB); | |
1265 | goto end; | |
1266 | } | |
1267 | /* Append the decoded extension to the serverinfo buffer */ | |
1268 | serverinfo = OPENSSL_realloc(serverinfo, serverinfo_length + extension_length); | |
1269 | if (serverinfo == NULL) | |
1270 | { | |
1271 | SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_MALLOC_FAILURE); | |
1272 | goto end; | |
1273 | } | |
1274 | memcpy(serverinfo + serverinfo_length, extension, extension_length); | |
1275 | serverinfo_length += extension_length; | |
1276 | ||
1277 | OPENSSL_free(name); name = NULL; | |
1278 | OPENSSL_free(header); header = NULL; | |
1279 | OPENSSL_free(extension); extension = NULL; | |
1280 | } | |
1281 | ||
1282 | ret = SSL_CTX_use_serverinfo(ctx, serverinfo, serverinfo_length); | |
1283 | end: | |
1284 | /* SSL_CTX_use_serverinfo makes a local copy of the serverinfo. */ | |
1285 | OPENSSL_free(name); | |
1286 | OPENSSL_free(header); | |
1287 | OPENSSL_free(extension); | |
1288 | OPENSSL_free(serverinfo); | |
1289 | if (bin != NULL) | |
1290 | BIO_free(bin); | |
1291 | return ret; | |
1292 | } | |
835d104f | 1293 | #endif /* OPENSSL_NO_STDIO */ |
8a02a46a | 1294 | #endif /* OPENSSL_NO_TLSEXT */ |