Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / boringssl / src / 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 #include <assert.h>
59 #include <ctype.h>
60 #include <stdio.h>
61
62 #include <openssl/base64.h>
63 #include <openssl/buf.h>
64 #include <openssl/des.h>
65 #include <openssl/err.h>
66 #include <openssl/evp.h>
67 #include <openssl/mem.h>
68 #include <openssl/obj.h>
69 #include <openssl/pem.h>
70 #include <openssl/rand.h>
71 #include <openssl/x509.h>
72
73 #include "../evp/internal.h"
74
75
76 #define MIN_LENGTH      4
77
78 static int load_iv(char **fromp,unsigned char *to, int num);
79 static int check_pem(const char *nm, const char *name);
80 int pem_check_suffix(const char *pem_str, const char *suffix);
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                 {
114                 buf[j+i*2]  =map[(str[i]>>4)&0x0f];
115                 buf[j+i*2+1]=map[(str[i]   )&0x0f];
116                 }
117         buf[j+i*2]='\n';
118         buf[j+i*2+1]='\0';
119         }
120
121 #ifndef OPENSSL_NO_FP_API
122 void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x,
123                     pem_password_cb *cb, void *u)
124         {
125         BIO *b;
126         void *ret;
127
128         if ((b=BIO_new(BIO_s_file())) == NULL)
129                 {
130                 OPENSSL_PUT_ERROR(PEM, PEM_ASN1_read, ERR_R_BUF_LIB);
131                 return(0);
132                 }
133         BIO_set_fp(b,fp,BIO_NOCLOSE);
134         ret=PEM_ASN1_read_bio(d2i,name,b,x,cb,u);
135         BIO_free(b);
136         return(ret);
137         }
138 #endif
139
140 static int check_pem(const char *nm, const char *name)
141 {
142         /* Normal matching nm and name */
143         if (!strcmp(nm,name)) return 1;
144
145         /* Make PEM_STRING_EVP_PKEY match any private key */
146
147         if(!strcmp(name,PEM_STRING_EVP_PKEY))
148                 {
149                 int slen;
150                 const EVP_PKEY_ASN1_METHOD *ameth;
151                 if(!strcmp(nm,PEM_STRING_PKCS8))
152                         return 1;
153                 if(!strcmp(nm,PEM_STRING_PKCS8INF))
154                         return 1;
155                 slen = pem_check_suffix(nm, "PRIVATE KEY"); 
156                 if (slen > 0)
157                         {
158                         /* NB: ENGINE implementations wont contain
159                          * a deprecated old private key decode function
160                          * so don't look for them.
161                          */
162                         ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen);
163                         if (ameth && ameth->old_priv_decode)
164                                 return 1;
165                         }
166                 return 0;
167                 }
168
169         if(!strcmp(name,PEM_STRING_PARAMETERS))
170                 {
171                 int slen;
172                 const EVP_PKEY_ASN1_METHOD *ameth;
173                 slen = pem_check_suffix(nm, "PARAMETERS"); 
174                 if (slen > 0)
175                         {
176                         ENGINE *e;
177                         ameth = EVP_PKEY_asn1_find_str(&e, nm, slen);
178                         if (ameth)
179                                 {
180                                 int r;
181                                 if (ameth->param_decode)
182                                         r = 1;
183                                 else
184                                         r = 0;
185                                 return r;
186                                 }
187                         }
188                 return 0;
189                 }
190         /* If reading DH parameters handle X9.42 DH format too */
191         if(!strcmp(nm,PEM_STRING_DHXPARAMS) &&
192                 !strcmp(name,PEM_STRING_DHPARAMS)) return 1;
193
194         /* Permit older strings */
195
196         if(!strcmp(nm,PEM_STRING_X509_OLD) &&
197                 !strcmp(name,PEM_STRING_X509)) return 1;
198
199         if(!strcmp(nm,PEM_STRING_X509_REQ_OLD) &&
200                 !strcmp(name,PEM_STRING_X509_REQ)) return 1;
201
202         /* Allow normal certs to be read as trusted certs */
203         if(!strcmp(nm,PEM_STRING_X509) &&
204                 !strcmp(name,PEM_STRING_X509_TRUSTED)) return 1;
205
206         if(!strcmp(nm,PEM_STRING_X509_OLD) &&
207                 !strcmp(name,PEM_STRING_X509_TRUSTED)) return 1;
208
209         /* Some CAs use PKCS#7 with CERTIFICATE headers */
210         if(!strcmp(nm, PEM_STRING_X509) &&
211                 !strcmp(name, PEM_STRING_PKCS7)) return 1;
212
213         if(!strcmp(nm, PEM_STRING_PKCS7_SIGNED) &&
214                 !strcmp(name, PEM_STRING_PKCS7)) return 1;
215
216 #ifndef OPENSSL_NO_CMS
217         if(!strcmp(nm, PEM_STRING_X509) &&
218                 !strcmp(name, PEM_STRING_CMS)) return 1;
219         /* Allow CMS to be read from PKCS#7 headers */
220         if(!strcmp(nm, PEM_STRING_PKCS7) &&
221                 !strcmp(name, PEM_STRING_CMS)) return 1;
222 #endif
223
224         return 0;
225 }
226
227 int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp,
228              pem_password_cb *cb, void *u)
229         {
230         EVP_CIPHER_INFO cipher;
231         char *nm=NULL,*header=NULL;
232         unsigned char *data=NULL;
233         long len;
234         int ret = 0;
235
236         for (;;)
237                 {
238                 if (!PEM_read_bio(bp,&nm,&header,&data,&len)) {
239                         if(ERR_GET_REASON(ERR_peek_error()) ==
240                                 PEM_R_NO_START_LINE)
241                                 ERR_add_error_data(2, "Expecting: ", name);
242                         return 0;
243                 }
244                 if(check_pem(nm, name)) break;
245                 OPENSSL_free(nm);
246                 OPENSSL_free(header);
247                 OPENSSL_free(data);
248                 }
249         if (!PEM_get_EVP_CIPHER_INFO(header,&cipher)) goto err;
250         if (!PEM_do_header(&cipher,data,&len,cb,u)) goto err;
251
252         *pdata = data;
253         *plen = len;
254
255         if (pnm)
256                 *pnm = nm;
257
258         ret = 1;
259
260 err:
261         if (!ret || !pnm) OPENSSL_free(nm);
262         OPENSSL_free(header);
263         if (!ret) OPENSSL_free(data);
264         return ret;
265         }
266
267 #ifndef OPENSSL_NO_FP_API
268 int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp,
269                    void *x, const EVP_CIPHER *enc, unsigned char *kstr,
270                    int klen, pem_password_cb *callback, void *u)
271         {
272         BIO *b;
273         int ret;
274
275         if ((b=BIO_new(BIO_s_file())) == NULL)
276                 {
277                 OPENSSL_PUT_ERROR(PEM, PEM_ASN1_write, ERR_R_BUF_LIB);
278                 return(0);
279                 }
280         BIO_set_fp(b,fp,BIO_NOCLOSE);
281         ret=PEM_ASN1_write_bio(i2d,name,b,x,enc,kstr,klen,callback,u);
282         BIO_free(b);
283         return(ret);
284         }
285 #endif
286
287 int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
288                        void *x, const EVP_CIPHER *enc, unsigned char *kstr,
289                        int klen, pem_password_cb *callback, void *u)
290         {
291         EVP_CIPHER_CTX ctx;
292         int dsize=0,i,j,ret=0;
293         unsigned char *p,*data=NULL;
294         const char *objstr=NULL;
295         char buf[PEM_BUFSIZE];
296         unsigned char key[EVP_MAX_KEY_LENGTH];
297         unsigned char iv[EVP_MAX_IV_LENGTH];
298         
299         if (enc != NULL)
300                 {
301                 objstr=OBJ_nid2sn(EVP_CIPHER_nid(enc));
302                 if (objstr == NULL)
303                         {
304                         OPENSSL_PUT_ERROR(PEM, PEM_ASN1_write_bio, PEM_R_UNSUPPORTED_CIPHER);
305                         goto err;
306                         }
307                 }
308
309         if ((dsize=i2d(x,NULL)) < 0)
310                 {
311                 OPENSSL_PUT_ERROR(PEM, PEM_ASN1_write_bio, ERR_R_ASN1_LIB);
312                 dsize=0;
313                 goto err;
314                 }
315         /* dzise + 8 bytes are needed */
316         /* actually it needs the cipher block size extra... */
317         data=(unsigned char *)OPENSSL_malloc((unsigned int)dsize+20);
318         if (data == NULL)
319                 {
320                 OPENSSL_PUT_ERROR(PEM, PEM_ASN1_write_bio, ERR_R_MALLOC_FAILURE);
321                 goto err;
322                 }
323         p=data;
324         i=i2d(x,&p);
325
326         if (enc != NULL)
327                 {
328                 const unsigned iv_len = EVP_CIPHER_iv_length(enc);
329
330                 if (kstr == NULL)
331                         {
332                         klen = 0;
333                         if (callback)
334                                 klen=(*callback)(buf,PEM_BUFSIZE,1,u);
335                         if (klen <= 0)
336                                 {
337                                 OPENSSL_PUT_ERROR(PEM, PEM_ASN1_write_bio, PEM_R_READ_KEY);
338                                 goto err;
339                                 }
340                         kstr=(unsigned char *)buf;
341                         }
342                 assert(iv_len <= (int)sizeof(iv));
343                 if (RAND_pseudo_bytes(iv,iv_len) < 0) /* Generate a salt */
344                         goto err;
345                 /* The 'iv' is used as the iv and as a salt.  It is
346                  * NOT taken from the BytesToKey function */
347                 if (!EVP_BytesToKey(enc,EVP_md5(),iv,kstr,klen,1,key,NULL))
348                         goto err;
349
350                 if (kstr == (unsigned char *)buf) OPENSSL_cleanse(buf,PEM_BUFSIZE);
351
352                 assert(strlen(objstr)+23+2*iv_len+13 <= sizeof buf);
353
354                 buf[0]='\0';
355                 PEM_proc_type(buf,PEM_TYPE_ENCRYPTED);
356                 PEM_dek_info(buf,objstr,iv_len,(char *)iv);
357                 /* k=strlen(buf); */
358
359                 EVP_CIPHER_CTX_init(&ctx);
360                 ret = 1;
361                 if (!EVP_EncryptInit_ex(&ctx,enc,NULL,key,iv)
362                         || !EVP_EncryptUpdate(&ctx,data,&j,data,i)
363                         || !EVP_EncryptFinal_ex(&ctx,&(data[j]),&i))
364                         ret = 0;
365                 EVP_CIPHER_CTX_cleanup(&ctx);
366                 if (ret == 0)
367                         goto err;
368                 i+=j;
369                 }
370         else
371                 {
372                 ret=1;
373                 buf[0]='\0';
374                 }
375         i=PEM_write_bio(bp,name,buf,data,i);
376         if (i <= 0) ret=0;
377 err:
378         OPENSSL_cleanse(key,sizeof(key));
379         OPENSSL_cleanse(iv,sizeof(iv));
380         OPENSSL_cleanse((char *)&ctx,sizeof(ctx));
381         OPENSSL_cleanse(buf,PEM_BUFSIZE);
382         if (data != NULL)
383                 {
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) return(1);
402
403         klen = 0;
404         if (callback)
405                 klen=callback(buf,PEM_BUFSIZE,0,u);
406         if (klen <= 0)
407                 {
408                 OPENSSL_PUT_ERROR(PEM, PEM_do_header, PEM_R_BAD_PASSWORD_READ);
409                 return(0);
410                 }
411
412         if (!EVP_BytesToKey(cipher->cipher,EVP_md5(),&(cipher->iv[0]),
413                 (unsigned char *)buf,klen,1,key,NULL))
414                 return 0;
415
416         j=(int)len;
417         EVP_CIPHER_CTX_init(&ctx);
418         o = EVP_DecryptInit_ex(&ctx,cipher->cipher,NULL, key,&(cipher->iv[0]));
419         if (o)
420                 o = EVP_DecryptUpdate(&ctx,data,&i,data,j);
421         if (o)
422                 o = EVP_DecryptFinal_ex(&ctx,&(data[i]),&j);
423         EVP_CIPHER_CTX_cleanup(&ctx);
424         OPENSSL_cleanse((char *)buf,sizeof(buf));
425         OPENSSL_cleanse((char *)key,sizeof(key));
426         if (!o)
427                 {
428                 OPENSSL_PUT_ERROR(PEM, PEM_do_header, PEM_R_BAD_DECRYPT);
429                 return(0);
430                 }
431         j+=i;
432         *plen=j;
433         return(1);
434         }
435
436 static const EVP_CIPHER* cipher_by_name(const char *name) {
437   if (strcmp(name, "DES-CBC") == 0) {
438     return EVP_des_cbc();
439   } else if (strcmp(name, "AES-128-CBC") == 0) {
440     return EVP_aes_128_cbc();
441   } else if (strcmp(name,  "AES-256-CBC") == 0) {
442     return EVP_aes_256_cbc();
443   } else {
444     return NULL;
445   }
446 }
447
448 int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher)
449         {
450         const EVP_CIPHER *enc=NULL;
451         char *p,c;
452         char **header_pp = &header;
453
454         cipher->cipher=NULL;
455         if ((header == NULL) || (*header == '\0') || (*header == '\n'))
456                 return(1);
457         if (strncmp(header,"Proc-Type: ",11) != 0)
458                 { OPENSSL_PUT_ERROR(PEM, PEM_get_EVP_CIPHER_INFO, PEM_R_NOT_PROC_TYPE); return(0); }
459         header+=11;
460         if (*header != '4') return(0); header++;
461         if (*header != ',') return(0); header++;
462         if (strncmp(header,"ENCRYPTED",9) != 0)
463                 { OPENSSL_PUT_ERROR(PEM, PEM_get_EVP_CIPHER_INFO, PEM_R_NOT_ENCRYPTED); return(0); }
464         for (; (*header != '\n') && (*header != '\0'); header++)
465                 ;
466         if (*header == '\0')
467                 { OPENSSL_PUT_ERROR(PEM, PEM_get_EVP_CIPHER_INFO, PEM_R_SHORT_HEADER); return(0); }
468         header++;
469         if (strncmp(header,"DEK-Info: ",10) != 0)
470                 { OPENSSL_PUT_ERROR(PEM, PEM_get_EVP_CIPHER_INFO, PEM_R_NOT_DEK_INFO); return(0); }
471         header+=10;
472
473         p=header;
474         for (;;)
475                 {
476                 c= *header;
477                 if (!(  ((c >= 'A') && (c <= 'Z')) || (c == '-') ||
478                         ((c >= '0') && (c <= '9'))))
479                         break;
480                 header++;
481                 }
482         *header='\0';
483         cipher->cipher=enc=cipher_by_name(p);
484         *header=c;
485         header++;
486
487         if (enc == NULL)
488                 {
489                 OPENSSL_PUT_ERROR(PEM, PEM_get_EVP_CIPHER_INFO, PEM_R_UNSUPPORTED_ENCRYPTION);
490                 return(0);
491                 }
492         if (!load_iv(header_pp,&(cipher->iv[0]),EVP_CIPHER_iv_length(enc)))
493                 return(0);
494
495         return(1);
496         }
497
498 static int load_iv(char **fromp, unsigned char *to, int num)
499         {
500         int v,i;
501         char *from;
502
503         from= *fromp;
504         for (i=0; i<num; i++) to[i]=0;
505         num*=2;
506         for (i=0; i<num; i++)
507                 {
508                 if ((*from >= '0') && (*from <= '9'))
509                         v= *from-'0';
510                 else if ((*from >= 'A') && (*from <= 'F'))
511                         v= *from-'A'+10;
512                 else if ((*from >= 'a') && (*from <= 'f'))
513                         v= *from-'a'+10;
514                 else
515                         {
516                         OPENSSL_PUT_ERROR(PEM, load_iv, PEM_R_BAD_IV_CHARS);
517                         return(0);
518                         }
519                 from++;
520                 to[i/2]|=v<<(long)((!(i&1))*4);
521                 }
522
523         *fromp=from;
524         return(1);
525         }
526
527 #ifndef OPENSSL_NO_FP_API
528 int PEM_write(FILE *fp, const char *name, const char *header,
529               const unsigned char *data, long len)
530         {
531         BIO *b;
532         int ret;
533
534         if ((b=BIO_new(BIO_s_file())) == NULL)
535                 {
536                 OPENSSL_PUT_ERROR(PEM, 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, const char *header,
547                   const 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                 {
565                 if (    (BIO_write(bp,header,i) != i) ||
566                         (BIO_write(bp,"\n",1) != 1))
567                         goto err;
568                 }
569
570         buf = OPENSSL_malloc(PEM_BUFSIZE*8);
571         if (buf == NULL)
572                 {
573                 reason=ERR_R_MALLOC_FAILURE;
574                 goto err;
575                 }
576
577         i=j=0;
578         while (len > 0)
579                 {
580                 n=(int)((len>(PEM_BUFSIZE*5))?(PEM_BUFSIZE*5):len);
581                 EVP_EncodeUpdate(&ctx,buf,&outl,&(data[j]),n);
582                 if ((outl) && (BIO_write(bp,(char *)buf,outl) != outl))
583                         goto err;
584                 i+=outl;
585                 len-=n;
586                 j+=n;
587                 }
588         EVP_EncodeFinal(&ctx,buf,&outl);
589         if ((outl > 0) && (BIO_write(bp,(char *)buf,outl) != outl)) goto err;
590         OPENSSL_cleanse(buf, PEM_BUFSIZE*8);
591         OPENSSL_free(buf);
592         buf = NULL;
593         if (    (BIO_write(bp,"-----END ",9) != 9) ||
594                 (BIO_write(bp,name,nlen) != nlen) ||
595                 (BIO_write(bp,"-----\n",6) != 6))
596                 goto err;
597         return(i+outl);
598 err:
599         if (buf) {
600                 OPENSSL_cleanse(buf, PEM_BUFSIZE*8);
601                 OPENSSL_free(buf);
602         }
603         OPENSSL_PUT_ERROR(PEM, PEM_write_bio, reason);
604         return(0);
605         }
606
607 #ifndef OPENSSL_NO_FP_API
608 int PEM_read(FILE *fp, char **name, char **header, unsigned char **data,
609              long *len)
610         {
611         BIO *b;
612         int ret;
613
614         if ((b=BIO_new(BIO_s_file())) == NULL)
615                 {
616                 OPENSSL_PUT_ERROR(PEM, PEM_read, ERR_R_BUF_LIB);
617                 return(0);
618                 }
619         BIO_set_fp(b,fp,BIO_NOCLOSE);
620         ret=PEM_read_bio(b, name, header, data,len);
621         BIO_free(b);
622         return(ret);
623         }
624 #endif
625
626 int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
627              long *len)
628         {
629         EVP_ENCODE_CTX ctx;
630         int end=0,i,k,bl=0,hl=0,nohead=0;
631         char buf[256];
632         BUF_MEM *nameB;
633         BUF_MEM *headerB;
634         BUF_MEM *dataB,*tmpB;
635         
636         nameB=BUF_MEM_new();
637         headerB=BUF_MEM_new();
638         dataB=BUF_MEM_new();
639         if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL))
640                 {
641                 BUF_MEM_free(nameB);
642                 BUF_MEM_free(headerB);
643                 BUF_MEM_free(dataB);
644                 OPENSSL_PUT_ERROR(PEM, PEM_read_bio, ERR_R_MALLOC_FAILURE);
645                 return(0);
646                 }
647
648         buf[254]='\0';
649         for (;;)
650                 {
651                 i=BIO_gets(bp,buf,254);
652
653                 if (i <= 0)
654                         {
655                         OPENSSL_PUT_ERROR(PEM, PEM_read_bio, PEM_R_NO_START_LINE);
656                         goto err;
657                         }
658
659                 while ((i >= 0) && (buf[i] <= ' ')) i--;
660                 buf[++i]='\n'; buf[++i]='\0';
661
662                 if (strncmp(buf,"-----BEGIN ",11) == 0)
663                         {
664                         i=strlen(&(buf[11]));
665
666                         if (strncmp(&(buf[11+i-6]),"-----\n",6) != 0)
667                                 continue;
668                         if (!BUF_MEM_grow(nameB,i+9))
669                                 {
670                                 OPENSSL_PUT_ERROR(PEM, PEM_read_bio, ERR_R_MALLOC_FAILURE);
671                                 goto err;
672                                 }
673                         memcpy(nameB->data,&(buf[11]),i-6);
674                         nameB->data[i-6]='\0';
675                         break;
676                         }
677                 }
678         hl=0;
679         if (!BUF_MEM_grow(headerB,256))
680                 { OPENSSL_PUT_ERROR(PEM, PEM_read_bio, ERR_R_MALLOC_FAILURE); goto err; }
681         headerB->data[0]='\0';
682         for (;;)
683                 {
684                 i=BIO_gets(bp,buf,254);
685                 if (i <= 0) break;
686
687                 while ((i >= 0) && (buf[i] <= ' ')) i--;
688                 buf[++i]='\n'; buf[++i]='\0';
689
690                 if (buf[0] == '\n') break;
691                 if (!BUF_MEM_grow(headerB,hl+i+9))
692                         { OPENSSL_PUT_ERROR(PEM, PEM_read_bio, ERR_R_MALLOC_FAILURE); goto err; }
693                 if (strncmp(buf,"-----END ",9) == 0)
694                         {
695                         nohead=1;
696                         break;
697                         }
698                 memcpy(&(headerB->data[hl]),buf,i);
699                 headerB->data[hl+i]='\0';
700                 hl+=i;
701                 }
702
703         bl=0;
704         if (!BUF_MEM_grow(dataB,1024))
705                 { OPENSSL_PUT_ERROR(PEM, PEM_read_bio, ERR_R_MALLOC_FAILURE); goto err; }
706         dataB->data[0]='\0';
707         if (!nohead)
708                 {
709                 for (;;)
710                         {
711                         i=BIO_gets(bp,buf,254);
712                         if (i <= 0) break;
713
714                         while ((i >= 0) && (buf[i] <= ' ')) i--;
715                         buf[++i]='\n'; buf[++i]='\0';
716
717                         if (i != 65) end=1;
718                         if (strncmp(buf,"-----END ",9) == 0)
719                                 break;
720                         if (i > 65) break;
721                         if (!BUF_MEM_grow_clean(dataB,i+bl+9))
722                                 {
723                                 OPENSSL_PUT_ERROR(PEM, PEM_read_bio, ERR_R_MALLOC_FAILURE);
724                                 goto err;
725                                 }
726                         memcpy(&(dataB->data[bl]),buf,i);
727                         dataB->data[bl+i]='\0';
728                         bl+=i;
729                         if (end)
730                                 {
731                                 buf[0]='\0';
732                                 i=BIO_gets(bp,buf,254);
733                                 if (i <= 0) break;
734
735                                 while ((i >= 0) && (buf[i] <= ' ')) i--;
736                                 buf[++i]='\n'; buf[++i]='\0';
737
738                                 break;
739                                 }
740                         }
741                 }
742         else
743                 {
744                 tmpB=headerB;
745                 headerB=dataB;
746                 dataB=tmpB;
747                 bl=hl;
748                 }
749         i=strlen(nameB->data);
750         if (    (strncmp(buf,"-----END ",9) != 0) ||
751                 (strncmp(nameB->data,&(buf[9]),i) != 0) ||
752                 (strncmp(&(buf[9+i]),"-----\n",6) != 0))
753                 {
754                 OPENSSL_PUT_ERROR(PEM, PEM_read_bio, PEM_R_BAD_END_LINE);
755                 goto err;
756                 }
757
758         EVP_DecodeInit(&ctx);
759         i=EVP_DecodeUpdate(&ctx,
760                 (unsigned char *)dataB->data,&bl,
761                 (unsigned char *)dataB->data,bl);
762         if (i < 0)
763                 {
764                 OPENSSL_PUT_ERROR(PEM, PEM_read_bio, PEM_R_BAD_BASE64_DECODE);
765                 goto err;
766                 }
767         i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k);
768         if (i < 0)
769                 {
770                 OPENSSL_PUT_ERROR(PEM, PEM_read_bio, PEM_R_BAD_BASE64_DECODE);
771                 goto err;
772                 }
773         bl+=k;
774
775         if (bl == 0) goto err;
776         *name=nameB->data;
777         *header=headerB->data;
778         *data=(unsigned char *)dataB->data;
779         *len=bl;
780         OPENSSL_free(nameB);
781         OPENSSL_free(headerB);
782         OPENSSL_free(dataB);
783         return(1);
784 err:
785         BUF_MEM_free(nameB);
786         BUF_MEM_free(headerB);
787         BUF_MEM_free(dataB);
788         return(0);
789         }
790
791 /* Check pem string and return prefix length.
792  * If for example the pem_str == "RSA PRIVATE KEY" and suffix = "PRIVATE KEY"
793  * the return value is 3 for the string "RSA".
794  */
795
796 int pem_check_suffix(const char *pem_str, const char *suffix)
797         {
798         int pem_len = strlen(pem_str);
799         int suffix_len = strlen(suffix);
800         const char *p;
801         if (suffix_len + 1 >= pem_len)
802                 return 0;
803         p = pem_str + pem_len - suffix_len;
804         if (strcmp(p, suffix))
805                 return 0;
806         p--;
807         if (*p != ' ')
808                 return 0;
809         return p - pem_str;
810         }
811