1 | /* crypto/pem/pem_lib.c */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
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 | #include <assert.h> |
59 | #include <ctype.h> |
60 | #include <stdio.h> |
61 | #include <string.h> |
62 | |
63 | #include <openssl/base64.h> |
64 | #include <openssl/buf.h> |
65 | #include <openssl/des.h> |
66 | #include <openssl/err.h> |
67 | #include <openssl/evp.h> |
68 | #include <openssl/mem.h> |
69 | #include <openssl/obj.h> |
70 | #include <openssl/pem.h> |
71 | #include <openssl/rand.h> |
72 | #include <openssl/x509.h> |
73 | |
74 | #include "../internal.h" |
75 | |
76 | |
77 | #define MIN_LENGTH 4 |
78 | |
79 | static int load_iv(char **fromp, unsigned char *to, int num); |
80 | static int check_pem(const char *nm, const char *name); |
81 | |
82 | void PEM_proc_type(char *buf, int type) |
83 | { |
84 | const char *str; |
85 | |
86 | if (type == PEM_TYPE_ENCRYPTED) |
87 | str = "ENCRYPTED" ; |
88 | else if (type == PEM_TYPE_MIC_CLEAR) |
89 | str = "MIC-CLEAR" ; |
90 | else if (type == PEM_TYPE_MIC_ONLY) |
91 | str = "MIC-ONLY" ; |
92 | else |
93 | str = "BAD-TYPE" ; |
94 | |
95 | BUF_strlcat(buf, "Proc-Type: 4," , PEM_BUFSIZE); |
96 | BUF_strlcat(buf, str, PEM_BUFSIZE); |
97 | BUF_strlcat(buf, "\n" , PEM_BUFSIZE); |
98 | } |
99 | |
100 | void PEM_dek_info(char *buf, const char *type, int len, char *str) |
101 | { |
102 | static const unsigned char map[17] = "0123456789ABCDEF" ; |
103 | long i; |
104 | int j; |
105 | |
106 | BUF_strlcat(buf, "DEK-Info: " , PEM_BUFSIZE); |
107 | BUF_strlcat(buf, type, PEM_BUFSIZE); |
108 | BUF_strlcat(buf, "," , PEM_BUFSIZE); |
109 | j = strlen(buf); |
110 | if (j + (len * 2) + 1 > PEM_BUFSIZE) |
111 | return; |
112 | for (i = 0; i < len; i++) { |
113 | buf[j + i * 2] = map[(str[i] >> 4) & 0x0f]; |
114 | buf[j + i * 2 + 1] = map[(str[i]) & 0x0f]; |
115 | } |
116 | buf[j + i * 2] = '\n'; |
117 | buf[j + i * 2 + 1] = '\0'; |
118 | } |
119 | |
120 | #ifndef OPENSSL_NO_FP_API |
121 | void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x, |
122 | pem_password_cb *cb, void *u) |
123 | { |
124 | BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); |
125 | if (b == NULL) { |
126 | OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); |
127 | return NULL; |
128 | } |
129 | void *ret = PEM_ASN1_read_bio(d2i, name, b, x, cb, u); |
130 | BIO_free(b); |
131 | return ret; |
132 | } |
133 | #endif |
134 | |
135 | static int check_pem(const char *nm, const char *name) |
136 | { |
137 | /* Normal matching nm and name */ |
138 | if (!strcmp(nm, name)) |
139 | return 1; |
140 | |
141 | /* Make PEM_STRING_EVP_PKEY match any private key */ |
142 | |
143 | if (!strcmp(name, PEM_STRING_EVP_PKEY)) { |
144 | return !strcmp(nm, PEM_STRING_PKCS8) || |
145 | !strcmp(nm, PEM_STRING_PKCS8INF) || |
146 | !strcmp(nm, PEM_STRING_RSA) || |
147 | !strcmp(nm, PEM_STRING_EC) || |
148 | !strcmp(nm, PEM_STRING_DSA); |
149 | } |
150 | |
151 | /* Permit older strings */ |
152 | |
153 | if (!strcmp(nm, PEM_STRING_X509_OLD) && !strcmp(name, PEM_STRING_X509)) |
154 | return 1; |
155 | |
156 | if (!strcmp(nm, PEM_STRING_X509_REQ_OLD) && |
157 | !strcmp(name, PEM_STRING_X509_REQ)) |
158 | return 1; |
159 | |
160 | /* Allow normal certs to be read as trusted certs */ |
161 | if (!strcmp(nm, PEM_STRING_X509) && |
162 | !strcmp(name, PEM_STRING_X509_TRUSTED)) |
163 | return 1; |
164 | |
165 | if (!strcmp(nm, PEM_STRING_X509_OLD) && |
166 | !strcmp(name, PEM_STRING_X509_TRUSTED)) |
167 | return 1; |
168 | |
169 | /* Some CAs use PKCS#7 with CERTIFICATE headers */ |
170 | if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_PKCS7)) |
171 | return 1; |
172 | |
173 | if (!strcmp(nm, PEM_STRING_PKCS7_SIGNED) && |
174 | !strcmp(name, PEM_STRING_PKCS7)) |
175 | return 1; |
176 | |
177 | #ifndef OPENSSL_NO_CMS |
178 | if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_CMS)) |
179 | return 1; |
180 | /* Allow CMS to be read from PKCS#7 headers */ |
181 | if (!strcmp(nm, PEM_STRING_PKCS7) && !strcmp(name, PEM_STRING_CMS)) |
182 | return 1; |
183 | #endif |
184 | |
185 | return 0; |
186 | } |
187 | |
188 | static const EVP_CIPHER *cipher_by_name(const char *name) |
189 | { |
190 | /* This is similar to the (deprecated) function |EVP_get_cipherbyname|. Note |
191 | * the PEM code assumes that ciphers have at least 8 bytes of IV, at most 20 |
192 | * bytes of overhead and generally behave like CBC mode. */ |
193 | if (0 == strcmp(name, SN_des_cbc)) { |
194 | return EVP_des_cbc(); |
195 | } else if (0 == strcmp(name, SN_des_ede3_cbc)) { |
196 | return EVP_des_ede3_cbc(); |
197 | } else if (0 == strcmp(name, SN_aes_128_cbc)) { |
198 | return EVP_aes_128_cbc(); |
199 | } else if (0 == strcmp(name, SN_aes_192_cbc)) { |
200 | return EVP_aes_192_cbc(); |
201 | } else if (0 == strcmp(name, SN_aes_256_cbc)) { |
202 | return EVP_aes_256_cbc(); |
203 | } else { |
204 | return NULL; |
205 | } |
206 | } |
207 | |
208 | int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, |
209 | const char *name, BIO *bp, pem_password_cb *cb, |
210 | void *u) |
211 | { |
212 | EVP_CIPHER_INFO cipher; |
213 | char *nm = NULL, * = NULL; |
214 | unsigned char *data = NULL; |
215 | long len; |
216 | int ret = 0; |
217 | |
218 | for (;;) { |
219 | if (!PEM_read_bio(bp, &nm, &header, &data, &len)) { |
220 | uint32_t error = ERR_peek_error(); |
221 | if (ERR_GET_LIB(error) == ERR_LIB_PEM && |
222 | ERR_GET_REASON(error) == PEM_R_NO_START_LINE) { |
223 | ERR_add_error_data(2, "Expecting: " , name); |
224 | } |
225 | return 0; |
226 | } |
227 | if (check_pem(nm, name)) |
228 | break; |
229 | OPENSSL_free(nm); |
230 | OPENSSL_free(header); |
231 | OPENSSL_free(data); |
232 | } |
233 | if (!PEM_get_EVP_CIPHER_INFO(header, &cipher)) |
234 | goto err; |
235 | if (!PEM_do_header(&cipher, data, &len, cb, u)) |
236 | goto err; |
237 | |
238 | *pdata = data; |
239 | *plen = len; |
240 | |
241 | if (pnm) |
242 | *pnm = nm; |
243 | |
244 | ret = 1; |
245 | |
246 | err: |
247 | if (!ret || !pnm) |
248 | OPENSSL_free(nm); |
249 | OPENSSL_free(header); |
250 | if (!ret) |
251 | OPENSSL_free(data); |
252 | return ret; |
253 | } |
254 | |
255 | #ifndef OPENSSL_NO_FP_API |
256 | int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, |
257 | void *x, const EVP_CIPHER *enc, unsigned char *kstr, |
258 | int klen, pem_password_cb *callback, void *u) |
259 | { |
260 | BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); |
261 | if (b == NULL) { |
262 | OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); |
263 | return 0; |
264 | } |
265 | int ret = PEM_ASN1_write_bio(i2d, name, b, x, enc, kstr, klen, callback, u); |
266 | BIO_free(b); |
267 | return ret; |
268 | } |
269 | #endif |
270 | |
271 | int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, |
272 | void *x, const EVP_CIPHER *enc, unsigned char *kstr, |
273 | int klen, pem_password_cb *callback, void *u) |
274 | { |
275 | EVP_CIPHER_CTX ctx; |
276 | int dsize = 0, i, j, ret = 0; |
277 | unsigned char *p, *data = NULL; |
278 | const char *objstr = NULL; |
279 | char buf[PEM_BUFSIZE]; |
280 | unsigned char key[EVP_MAX_KEY_LENGTH]; |
281 | unsigned char iv[EVP_MAX_IV_LENGTH]; |
282 | |
283 | if (enc != NULL) { |
284 | objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc)); |
285 | if (objstr == NULL || |
286 | cipher_by_name(objstr) == NULL || |
287 | EVP_CIPHER_iv_length(enc) < 8) { |
288 | OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER); |
289 | goto err; |
290 | } |
291 | } |
292 | |
293 | if ((dsize = i2d(x, NULL)) < 0) { |
294 | OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB); |
295 | dsize = 0; |
296 | goto err; |
297 | } |
298 | /* dzise + 8 bytes are needed */ |
299 | /* actually it needs the cipher block size extra... */ |
300 | data = (unsigned char *)OPENSSL_malloc((unsigned int)dsize + 20); |
301 | if (data == NULL) { |
302 | OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); |
303 | goto err; |
304 | } |
305 | p = data; |
306 | i = i2d(x, &p); |
307 | |
308 | if (enc != NULL) { |
309 | const unsigned iv_len = EVP_CIPHER_iv_length(enc); |
310 | |
311 | if (kstr == NULL) { |
312 | klen = 0; |
313 | if (!callback) |
314 | callback = PEM_def_callback; |
315 | klen = (*callback) (buf, PEM_BUFSIZE, 1, u); |
316 | if (klen <= 0) { |
317 | OPENSSL_PUT_ERROR(PEM, PEM_R_READ_KEY); |
318 | goto err; |
319 | } |
320 | kstr = (unsigned char *)buf; |
321 | } |
322 | assert(iv_len <= (int)sizeof(iv)); |
323 | if (!RAND_bytes(iv, iv_len)) /* Generate a salt */ |
324 | goto err; |
325 | /* |
326 | * The 'iv' is used as the iv and as a salt. It is NOT taken from |
327 | * the BytesToKey function |
328 | */ |
329 | if (!EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1, key, NULL)) |
330 | goto err; |
331 | |
332 | if (kstr == (unsigned char *)buf) |
333 | OPENSSL_cleanse(buf, PEM_BUFSIZE); |
334 | |
335 | assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof buf); |
336 | |
337 | buf[0] = '\0'; |
338 | PEM_proc_type(buf, PEM_TYPE_ENCRYPTED); |
339 | PEM_dek_info(buf, objstr, iv_len, (char *)iv); |
340 | /* k=strlen(buf); */ |
341 | |
342 | EVP_CIPHER_CTX_init(&ctx); |
343 | ret = 1; |
344 | if (!EVP_EncryptInit_ex(&ctx, enc, NULL, key, iv) |
345 | || !EVP_EncryptUpdate(&ctx, data, &j, data, i) |
346 | || !EVP_EncryptFinal_ex(&ctx, &(data[j]), &i)) |
347 | ret = 0; |
348 | else |
349 | i += j; |
350 | EVP_CIPHER_CTX_cleanup(&ctx); |
351 | if (ret == 0) |
352 | goto err; |
353 | } else { |
354 | ret = 1; |
355 | buf[0] = '\0'; |
356 | } |
357 | i = PEM_write_bio(bp, name, buf, data, i); |
358 | if (i <= 0) |
359 | ret = 0; |
360 | err: |
361 | OPENSSL_cleanse(key, sizeof(key)); |
362 | OPENSSL_cleanse(iv, sizeof(iv)); |
363 | OPENSSL_cleanse((char *)&ctx, sizeof(ctx)); |
364 | OPENSSL_cleanse(buf, PEM_BUFSIZE); |
365 | OPENSSL_free(data); |
366 | return (ret); |
367 | } |
368 | |
369 | int (EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen, |
370 | pem_password_cb *callback, void *u) |
371 | { |
372 | int i = 0, j, o, klen; |
373 | long len; |
374 | EVP_CIPHER_CTX ctx; |
375 | unsigned char key[EVP_MAX_KEY_LENGTH]; |
376 | char buf[PEM_BUFSIZE]; |
377 | |
378 | len = *plen; |
379 | |
380 | if (cipher->cipher == NULL) |
381 | return (1); |
382 | |
383 | klen = 0; |
384 | if (!callback) |
385 | callback = PEM_def_callback; |
386 | klen = callback(buf, PEM_BUFSIZE, 0, u); |
387 | if (klen <= 0) { |
388 | OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ); |
389 | return (0); |
390 | } |
391 | |
392 | if (!EVP_BytesToKey(cipher->cipher, EVP_md5(), &(cipher->iv[0]), |
393 | (unsigned char *)buf, klen, 1, key, NULL)) |
394 | return 0; |
395 | |
396 | j = (int)len; |
397 | EVP_CIPHER_CTX_init(&ctx); |
398 | o = EVP_DecryptInit_ex(&ctx, cipher->cipher, NULL, key, &(cipher->iv[0])); |
399 | if (o) |
400 | o = EVP_DecryptUpdate(&ctx, data, &i, data, j); |
401 | if (o) |
402 | o = EVP_DecryptFinal_ex(&ctx, &(data[i]), &j); |
403 | EVP_CIPHER_CTX_cleanup(&ctx); |
404 | OPENSSL_cleanse((char *)buf, sizeof(buf)); |
405 | OPENSSL_cleanse((char *)key, sizeof(key)); |
406 | if (!o) { |
407 | OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_DECRYPT); |
408 | return (0); |
409 | } |
410 | j += i; |
411 | *plen = j; |
412 | return (1); |
413 | } |
414 | |
415 | int PEM_get_EVP_CIPHER_INFO(char *, EVP_CIPHER_INFO *cipher) |
416 | { |
417 | const EVP_CIPHER *enc = NULL; |
418 | char *p, c; |
419 | char ** = &header; |
420 | |
421 | cipher->cipher = NULL; |
422 | OPENSSL_memset(cipher->iv, 0, sizeof(cipher->iv)); |
423 | if ((header == NULL) || (*header == '\0') || (*header == '\n')) |
424 | return (1); |
425 | if (strncmp(header, "Proc-Type: " , 11) != 0) { |
426 | OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_PROC_TYPE); |
427 | return (0); |
428 | } |
429 | header += 11; |
430 | if (*header != '4') |
431 | return (0); |
432 | header++; |
433 | if (*header != ',') |
434 | return (0); |
435 | header++; |
436 | if (strncmp(header, "ENCRYPTED" , 9) != 0) { |
437 | OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_ENCRYPTED); |
438 | return (0); |
439 | } |
440 | for (; (*header != '\n') && (*header != '\0'); header++) ; |
441 | if (*header == '\0') { |
442 | OPENSSL_PUT_ERROR(PEM, PEM_R_SHORT_HEADER); |
443 | return (0); |
444 | } |
445 | header++; |
446 | if (strncmp(header, "DEK-Info: " , 10) != 0) { |
447 | OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_DEK_INFO); |
448 | return (0); |
449 | } |
450 | header += 10; |
451 | |
452 | p = header; |
453 | for (;;) { |
454 | c = *header; |
455 | if (!(((c >= 'A') && (c <= 'Z')) || (c == '-') || |
456 | ((c >= '0') && (c <= '9')))) |
457 | break; |
458 | header++; |
459 | } |
460 | *header = '\0'; |
461 | cipher->cipher = enc = cipher_by_name(p); |
462 | *header = c; |
463 | header++; |
464 | |
465 | if (enc == NULL) { |
466 | OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_ENCRYPTION); |
467 | return (0); |
468 | } |
469 | // The IV parameter must be at least 8 bytes long to be used as the salt in |
470 | // the KDF. (This should not happen given |cipher_by_name|.) |
471 | if (EVP_CIPHER_iv_length(enc) < 8) { |
472 | assert(0); |
473 | OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_ENCRYPTION); |
474 | return 0; |
475 | } |
476 | if (!load_iv(header_pp, &(cipher->iv[0]), EVP_CIPHER_iv_length(enc))) |
477 | return (0); |
478 | |
479 | return (1); |
480 | } |
481 | |
482 | static int load_iv(char **fromp, unsigned char *to, int num) |
483 | { |
484 | int v, i; |
485 | char *from; |
486 | |
487 | from = *fromp; |
488 | for (i = 0; i < num; i++) |
489 | to[i] = 0; |
490 | num *= 2; |
491 | for (i = 0; i < num; i++) { |
492 | if ((*from >= '0') && (*from <= '9')) |
493 | v = *from - '0'; |
494 | else if ((*from >= 'A') && (*from <= 'F')) |
495 | v = *from - 'A' + 10; |
496 | else if ((*from >= 'a') && (*from <= 'f')) |
497 | v = *from - 'a' + 10; |
498 | else { |
499 | OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_IV_CHARS); |
500 | return (0); |
501 | } |
502 | from++; |
503 | to[i / 2] |= v << (long)((!(i & 1)) * 4); |
504 | } |
505 | |
506 | *fromp = from; |
507 | return (1); |
508 | } |
509 | |
510 | #ifndef OPENSSL_NO_FP_API |
511 | int PEM_write(FILE *fp, const char *name, const char *, |
512 | const unsigned char *data, long len) |
513 | { |
514 | BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); |
515 | if (b == NULL) { |
516 | OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); |
517 | return 0; |
518 | } |
519 | int ret = PEM_write_bio(b, name, header, data, len); |
520 | BIO_free(b); |
521 | return (ret); |
522 | } |
523 | #endif |
524 | |
525 | int PEM_write_bio(BIO *bp, const char *name, const char *, |
526 | const unsigned char *data, long len) |
527 | { |
528 | int nlen, n, i, j, outl; |
529 | unsigned char *buf = NULL; |
530 | EVP_ENCODE_CTX ctx; |
531 | int reason = ERR_R_BUF_LIB; |
532 | |
533 | EVP_EncodeInit(&ctx); |
534 | nlen = strlen(name); |
535 | |
536 | if ((BIO_write(bp, "-----BEGIN " , 11) != 11) || |
537 | (BIO_write(bp, name, nlen) != nlen) || |
538 | (BIO_write(bp, "-----\n" , 6) != 6)) |
539 | goto err; |
540 | |
541 | i = strlen(header); |
542 | if (i > 0) { |
543 | if ((BIO_write(bp, header, i) != i) || (BIO_write(bp, "\n" , 1) != 1)) |
544 | goto err; |
545 | } |
546 | |
547 | buf = OPENSSL_malloc(PEM_BUFSIZE * 8); |
548 | if (buf == NULL) { |
549 | reason = ERR_R_MALLOC_FAILURE; |
550 | goto err; |
551 | } |
552 | |
553 | i = j = 0; |
554 | while (len > 0) { |
555 | n = (int)((len > (PEM_BUFSIZE * 5)) ? (PEM_BUFSIZE * 5) : len); |
556 | EVP_EncodeUpdate(&ctx, buf, &outl, &(data[j]), n); |
557 | if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl)) |
558 | goto err; |
559 | i += outl; |
560 | len -= n; |
561 | j += n; |
562 | } |
563 | EVP_EncodeFinal(&ctx, buf, &outl); |
564 | if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl)) |
565 | goto err; |
566 | OPENSSL_free(buf); |
567 | buf = NULL; |
568 | if ((BIO_write(bp, "-----END " , 9) != 9) || |
569 | (BIO_write(bp, name, nlen) != nlen) || |
570 | (BIO_write(bp, "-----\n" , 6) != 6)) |
571 | goto err; |
572 | return (i + outl); |
573 | err: |
574 | if (buf) { |
575 | OPENSSL_free(buf); |
576 | } |
577 | OPENSSL_PUT_ERROR(PEM, reason); |
578 | return (0); |
579 | } |
580 | |
581 | #ifndef OPENSSL_NO_FP_API |
582 | int PEM_read(FILE *fp, char **name, char **, unsigned char **data, |
583 | long *len) |
584 | { |
585 | BIO *b = BIO_new_fp(fp, BIO_NOCLOSE); |
586 | if (b == NULL) { |
587 | OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB); |
588 | return 0; |
589 | } |
590 | int ret = PEM_read_bio(b, name, header, data, len); |
591 | BIO_free(b); |
592 | return (ret); |
593 | } |
594 | #endif |
595 | |
596 | int PEM_read_bio(BIO *bp, char **name, char **, unsigned char **data, |
597 | long *len) |
598 | { |
599 | EVP_ENCODE_CTX ctx; |
600 | int end = 0, i, k, bl = 0, hl = 0, nohead = 0; |
601 | char buf[256]; |
602 | BUF_MEM *nameB; |
603 | BUF_MEM *; |
604 | BUF_MEM *dataB, *tmpB; |
605 | |
606 | nameB = BUF_MEM_new(); |
607 | headerB = BUF_MEM_new(); |
608 | dataB = BUF_MEM_new(); |
609 | if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL)) { |
610 | BUF_MEM_free(nameB); |
611 | BUF_MEM_free(headerB); |
612 | BUF_MEM_free(dataB); |
613 | OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); |
614 | return (0); |
615 | } |
616 | |
617 | buf[254] = '\0'; |
618 | for (;;) { |
619 | i = BIO_gets(bp, buf, 254); |
620 | |
621 | if (i <= 0) { |
622 | OPENSSL_PUT_ERROR(PEM, PEM_R_NO_START_LINE); |
623 | goto err; |
624 | } |
625 | |
626 | while ((i >= 0) && (buf[i] <= ' ')) |
627 | i--; |
628 | buf[++i] = '\n'; |
629 | buf[++i] = '\0'; |
630 | |
631 | if (strncmp(buf, "-----BEGIN " , 11) == 0) { |
632 | i = strlen(&(buf[11])); |
633 | |
634 | if (strncmp(&(buf[11 + i - 6]), "-----\n" , 6) != 0) |
635 | continue; |
636 | if (!BUF_MEM_grow(nameB, i + 9)) { |
637 | OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); |
638 | goto err; |
639 | } |
640 | OPENSSL_memcpy(nameB->data, &(buf[11]), i - 6); |
641 | nameB->data[i - 6] = '\0'; |
642 | break; |
643 | } |
644 | } |
645 | hl = 0; |
646 | if (!BUF_MEM_grow(headerB, 256)) { |
647 | OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); |
648 | goto err; |
649 | } |
650 | headerB->data[0] = '\0'; |
651 | for (;;) { |
652 | i = BIO_gets(bp, buf, 254); |
653 | if (i <= 0) |
654 | break; |
655 | |
656 | while ((i >= 0) && (buf[i] <= ' ')) |
657 | i--; |
658 | buf[++i] = '\n'; |
659 | buf[++i] = '\0'; |
660 | |
661 | if (buf[0] == '\n') |
662 | break; |
663 | if (!BUF_MEM_grow(headerB, hl + i + 9)) { |
664 | OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); |
665 | goto err; |
666 | } |
667 | if (strncmp(buf, "-----END " , 9) == 0) { |
668 | nohead = 1; |
669 | break; |
670 | } |
671 | OPENSSL_memcpy(&(headerB->data[hl]), buf, i); |
672 | headerB->data[hl + i] = '\0'; |
673 | hl += i; |
674 | } |
675 | |
676 | bl = 0; |
677 | if (!BUF_MEM_grow(dataB, 1024)) { |
678 | OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); |
679 | goto err; |
680 | } |
681 | dataB->data[0] = '\0'; |
682 | if (!nohead) { |
683 | for (;;) { |
684 | i = BIO_gets(bp, buf, 254); |
685 | if (i <= 0) |
686 | break; |
687 | |
688 | while ((i >= 0) && (buf[i] <= ' ')) |
689 | i--; |
690 | buf[++i] = '\n'; |
691 | buf[++i] = '\0'; |
692 | |
693 | if (i != 65) |
694 | end = 1; |
695 | if (strncmp(buf, "-----END " , 9) == 0) |
696 | break; |
697 | if (i > 65) |
698 | break; |
699 | if (!BUF_MEM_grow_clean(dataB, i + bl + 9)) { |
700 | OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); |
701 | goto err; |
702 | } |
703 | OPENSSL_memcpy(&(dataB->data[bl]), buf, i); |
704 | dataB->data[bl + i] = '\0'; |
705 | bl += i; |
706 | if (end) { |
707 | buf[0] = '\0'; |
708 | i = BIO_gets(bp, buf, 254); |
709 | if (i <= 0) |
710 | break; |
711 | |
712 | while ((i >= 0) && (buf[i] <= ' ')) |
713 | i--; |
714 | buf[++i] = '\n'; |
715 | buf[++i] = '\0'; |
716 | |
717 | break; |
718 | } |
719 | } |
720 | } else { |
721 | tmpB = headerB; |
722 | headerB = dataB; |
723 | dataB = tmpB; |
724 | bl = hl; |
725 | } |
726 | i = strlen(nameB->data); |
727 | if ((strncmp(buf, "-----END " , 9) != 0) || |
728 | (strncmp(nameB->data, &(buf[9]), i) != 0) || |
729 | (strncmp(&(buf[9 + i]), "-----\n" , 6) != 0)) { |
730 | OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_END_LINE); |
731 | goto err; |
732 | } |
733 | |
734 | EVP_DecodeInit(&ctx); |
735 | i = EVP_DecodeUpdate(&ctx, |
736 | (unsigned char *)dataB->data, &bl, |
737 | (unsigned char *)dataB->data, bl); |
738 | if (i < 0) { |
739 | OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE); |
740 | goto err; |
741 | } |
742 | i = EVP_DecodeFinal(&ctx, (unsigned char *)&(dataB->data[bl]), &k); |
743 | if (i < 0) { |
744 | OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE); |
745 | goto err; |
746 | } |
747 | bl += k; |
748 | |
749 | if (bl == 0) |
750 | goto err; |
751 | *name = nameB->data; |
752 | *header = headerB->data; |
753 | *data = (unsigned char *)dataB->data; |
754 | *len = bl; |
755 | OPENSSL_free(nameB); |
756 | OPENSSL_free(headerB); |
757 | OPENSSL_free(dataB); |
758 | return (1); |
759 | err: |
760 | BUF_MEM_free(nameB); |
761 | BUF_MEM_free(headerB); |
762 | BUF_MEM_free(dataB); |
763 | return (0); |
764 | } |
765 | |
766 | int PEM_def_callback(char *buf, int size, int rwflag, void *userdata) |
767 | { |
768 | if (!buf || !userdata || size < 0) { |
769 | return 0; |
770 | } |
771 | size_t len = strlen((char *)userdata); |
772 | if (len >= (size_t)size) { |
773 | return 0; |
774 | } |
775 | BUF_strlcpy(buf, userdata, (size_t)size); |
776 | return len; |
777 | } |
778 | |