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