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