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