summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/pem/pem_lib.c
diff options
context:
space:
mode:
authorryker <>1998-10-05 20:13:14 +0000
committerryker <>1998-10-05 20:13:14 +0000
commitaeeae06a79815dc190061534d47236cec09f9e32 (patch)
tree851692b9c2f9c04f077666855641900f19fdb217 /src/lib/libcrypto/pem/pem_lib.c
parenta4f79641824cbf9f60ca9d1168d1fcc46717a82a (diff)
downloadopenbsd-aeeae06a79815dc190061534d47236cec09f9e32.tar.gz
openbsd-aeeae06a79815dc190061534d47236cec09f9e32.tar.bz2
openbsd-aeeae06a79815dc190061534d47236cec09f9e32.zip
Import of SSLeay-0.9.0b with RSA and IDEA stubbed + OpenBSD build
functionality for shared libs. Note that routines such as sslv2_init and friends that use RSA will not work due to lack of RSA in this library. Needs documentation and help from ports for easy upgrade to full functionality where legally possible.
Diffstat (limited to 'src/lib/libcrypto/pem/pem_lib.c')
-rw-r--r--src/lib/libcrypto/pem/pem_lib.c762
1 files changed, 762 insertions, 0 deletions
diff --git a/src/lib/libcrypto/pem/pem_lib.c b/src/lib/libcrypto/pem/pem_lib.c
new file mode 100644
index 0000000000..7a2c0ad83b
--- /dev/null
+++ b/src/lib/libcrypto/pem/pem_lib.c
@@ -0,0 +1,762 @@
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 "buffer.h"
62#include "objects.h"
63#include "evp.h"
64#include "rand.h"
65#include "x509.h"
66#include "pem.h"
67#ifndef NO_DES
68#include "des.h"
69#endif
70
71char *PEM_version="PEM part of SSLeay 0.9.0b 29-Jun-1998";
72
73#define MIN_LENGTH 4
74
75/* PEMerr(PEM_F_PEM_WRITE_BIO,ERR_R_MALLOC_FAILURE);
76 * PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
77 */
78
79#ifndef NOPROTO
80static int def_callback(char *buf, int num, int w);
81static int load_iv(unsigned char **fromp,unsigned char *to, int num);
82#else
83static int def_callback();
84static int load_iv();
85#endif
86
87static int def_callback(buf, num, w)
88char *buf;
89int num;
90int w;
91 {
92#ifdef NO_FP_API
93 /* We should not ever call the default callback routine from
94 * windows. */
95 PEMerr(PEM_F_DEF_CALLBACK,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
96 return(-1);
97#else
98 int i,j;
99 char *prompt;
100
101 prompt=EVP_get_pw_prompt();
102 if (prompt == NULL)
103 prompt="Enter PEM pass phrase:";
104
105 for (;;)
106 {
107 i=EVP_read_pw_string(buf,num,prompt,w);
108 if (i != 0)
109 {
110 PEMerr(PEM_F_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD);
111 memset(buf,0,(unsigned int)num);
112 return(-1);
113 }
114 j=strlen(buf);
115 if (j < MIN_LENGTH)
116 {
117 fprintf(stderr,"phrase is too short, needs to be at least %d chars\n",MIN_LENGTH);
118 }
119 else
120 break;
121 }
122 return(j);
123#endif
124 }
125
126void PEM_proc_type(buf, type)
127char *buf;
128int type;
129 {
130 char *str;
131
132 if (type == PEM_TYPE_ENCRYPTED)
133 str="ENCRYPTED";
134 else if (type == PEM_TYPE_MIC_CLEAR)
135 str="MIC-CLEAR";
136 else if (type == PEM_TYPE_MIC_ONLY)
137 str="MIC-ONLY";
138 else
139 str="BAD-TYPE";
140
141 strcat(buf,"Proc-Type: 4,");
142 strcat(buf,str);
143 strcat(buf,"\n");
144 }
145
146void PEM_dek_info(buf, type, len, str)
147char *buf;
148char *type;
149int len;
150char *str;
151 {
152 static unsigned char map[17]="0123456789ABCDEF";
153 long i;
154 int j;
155
156 strcat(buf,"DEK-Info: ");
157 strcat(buf,type);
158 strcat(buf,",");
159 j=strlen(buf);
160 for (i=0; i<len; i++)
161 {
162 buf[j+i*2] =map[(str[i]>>4)&0x0f];
163 buf[j+i*2+1]=map[(str[i] )&0x0f];
164 }
165 buf[j+i*2]='\n';
166 buf[j+i*2+1]='\0';
167 }
168
169#ifndef NO_FP_API
170char *PEM_ASN1_read(d2i,name,fp, x, cb)
171char *(*d2i)();
172char *name;
173FILE *fp;
174char **x;
175int (*cb)();
176 {
177 BIO *b;
178 char *ret;
179
180 if ((b=BIO_new(BIO_s_file())) == NULL)
181 {
182 PEMerr(PEM_F_PEM_ASN1_READ,ERR_R_BUF_LIB);
183 return(0);
184 }
185 BIO_set_fp(b,fp,BIO_NOCLOSE);
186 ret=PEM_ASN1_read_bio(d2i,name,b,x,cb);
187 BIO_free(b);
188 return(ret);
189 }
190#endif
191
192char *PEM_ASN1_read_bio(d2i,name,bp, x, cb)
193char *(*d2i)();
194char *name;
195BIO *bp;
196char **x;
197int (*cb)();
198 {
199 EVP_CIPHER_INFO cipher;
200 char *nm=NULL,*header=NULL;
201 unsigned char *p=NULL,*data=NULL;
202 long len;
203 char *ret=NULL;
204
205 for (;;)
206 {
207 if (!PEM_read_bio(bp,&nm,&header,&data,&len)) return(NULL);
208 if ( (strcmp(nm,name) == 0) ||
209 ((strcmp(nm,PEM_STRING_RSA) == 0) &&
210 (strcmp(name,PEM_STRING_EVP_PKEY) == 0)) ||
211 ((strcmp(nm,PEM_STRING_DSA) == 0) &&
212 (strcmp(name,PEM_STRING_EVP_PKEY) == 0)) ||
213 ((strcmp(nm,PEM_STRING_X509_OLD) == 0) &&
214 (strcmp(name,PEM_STRING_X509) == 0)) ||
215 ((strcmp(nm,PEM_STRING_X509_REQ_OLD) == 0) &&
216 (strcmp(name,PEM_STRING_X509_REQ) == 0))
217 )
218 break;
219 Free(nm);
220 Free(header);
221 Free(data);
222 }
223 if (!PEM_get_EVP_CIPHER_INFO(header,&cipher)) goto err;
224 if (!PEM_do_header(&cipher,data,&len,cb)) goto err;
225 p=data;
226 if (strcmp(name,PEM_STRING_EVP_PKEY) == 0)
227 {
228 if (strcmp(nm,PEM_STRING_RSA) == 0)
229 ret=d2i(EVP_PKEY_RSA,x,&p,len);
230 else if (strcmp(nm,PEM_STRING_DSA) == 0)
231 ret=d2i(EVP_PKEY_DSA,x,&p,len);
232 }
233 else
234 ret=d2i(x,&p,len);
235 if (ret == NULL)
236 PEMerr(PEM_F_PEM_ASN1_READ_BIO,ERR_R_ASN1_LIB);
237err:
238 Free(nm);
239 Free(header);
240 Free(data);
241 return(ret);
242 }
243
244#ifndef NO_FP_API
245int PEM_ASN1_write(i2d,name,fp, x, enc, kstr, klen, callback)
246int (*i2d)();
247char *name;
248FILE *fp;
249char *x;
250EVP_CIPHER *enc;
251unsigned char *kstr;
252int klen;
253int (*callback)();
254 {
255 BIO *b;
256 int ret;
257
258 if ((b=BIO_new(BIO_s_file())) == NULL)
259 {
260 PEMerr(PEM_F_PEM_ASN1_WRITE,ERR_R_BUF_LIB);
261 return(0);
262 }
263 BIO_set_fp(b,fp,BIO_NOCLOSE);
264 ret=PEM_ASN1_write_bio(i2d,name,b,x,enc,kstr,klen,callback);
265 BIO_free(b);
266 return(ret);
267 }
268#endif
269
270int PEM_ASN1_write_bio(i2d,name,bp, x, enc, kstr, klen, callback)
271int (*i2d)();
272char *name;
273BIO *bp;
274char *x;
275EVP_CIPHER *enc;
276unsigned char *kstr;
277int klen;
278int (*callback)();
279 {
280 EVP_CIPHER_CTX ctx;
281 int dsize=0,i,j,ret=0;
282 unsigned char *p,*data=NULL;
283 char *objstr=NULL;
284#define PEM_BUFSIZE 1024
285 char buf[PEM_BUFSIZE];
286 unsigned char key[EVP_MAX_KEY_LENGTH];
287 unsigned char iv[EVP_MAX_IV_LENGTH];
288
289 if (enc != NULL)
290 {
291 objstr=OBJ_nid2sn(EVP_CIPHER_nid(enc));
292 if (objstr == NULL)
293 {
294 PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_UNSUPPORTED_CIPHER);
295 goto err;
296 }
297 }
298
299 if ((dsize=i2d(x,NULL)) < 0)
300 {
301 PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_MALLOC_FAILURE);
302 dsize=0;
303 goto err;
304 }
305 /* dzise + 8 bytes are needed */
306 data=(unsigned char *)Malloc((unsigned int)dsize+20);
307 if (data == NULL)
308 {
309 PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_MALLOC_FAILURE);
310 goto err;
311 }
312 p=data;
313 i=i2d(x,&p);
314
315 if (enc != NULL)
316 {
317 if (kstr == NULL)
318 {
319 if (callback == NULL)
320 klen=def_callback(buf,PEM_BUFSIZE,1);
321 else
322 klen=(*callback)(buf,PEM_BUFSIZE,1);
323 if (klen <= 0)
324 {
325 PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_READ_KEY);
326 goto err;
327 }
328 kstr=(unsigned char *)buf;
329 }
330 RAND_seed(data,i);/* put in the RSA key. */
331 RAND_bytes(iv,8); /* Generate a salt */
332 /* The 'iv' is used as the iv and as a salt. It is
333 * NOT taken from the BytesToKey function */
334 EVP_BytesToKey(enc,EVP_md5(),iv,kstr,klen,1,key,NULL);
335
336 if (kstr == (unsigned char *)buf) memset(buf,0,PEM_BUFSIZE);
337
338 buf[0]='\0';
339 PEM_proc_type(buf,PEM_TYPE_ENCRYPTED);
340 PEM_dek_info(buf,objstr,8,(char *)iv);
341 /* k=strlen(buf); */
342
343 EVP_EncryptInit(&ctx,enc,key,iv);
344 EVP_EncryptUpdate(&ctx,data,&j,data,i);
345 EVP_EncryptFinal(&ctx,&(data[j]),&i);
346 i+=j;
347 ret=1;
348 }
349 else
350 {
351 ret=1;
352 buf[0]='\0';
353 }
354 i=PEM_write_bio(bp,name,buf,data,i);
355 if (i <= 0) ret=0;
356err:
357 memset(key,0,sizeof(key));
358 memset(iv,0,sizeof(iv));
359 memset((char *)&ctx,0,sizeof(ctx));
360 memset(buf,0,PEM_BUFSIZE);
361 memset(data,0,(unsigned int)dsize);
362 Free(data);
363 return(ret);
364 }
365
366int PEM_do_header(cipher, data, plen, callback)
367EVP_CIPHER_INFO *cipher;
368unsigned char *data;
369long *plen;
370int (*callback)();
371 {
372 int i,j,o,klen;
373 long len;
374 EVP_CIPHER_CTX ctx;
375 unsigned char key[EVP_MAX_KEY_LENGTH];
376 char buf[PEM_BUFSIZE];
377
378 len= *plen;
379
380 if (cipher->cipher == NULL) return(1);
381 if (callback == NULL)
382 klen=def_callback(buf,PEM_BUFSIZE,0);
383 else
384 klen=callback(buf,PEM_BUFSIZE,0);
385 if (klen <= 0)
386 {
387 PEMerr(PEM_F_PEM_DO_HEADER,PEM_R_BAD_PASSWORD_READ);
388 return(0);
389 }
390 EVP_BytesToKey(cipher->cipher,EVP_md5(),&(cipher->iv[0]),
391 (unsigned char *)buf,klen,1,key,NULL);
392
393 j=(int)len;
394 EVP_DecryptInit(&ctx,cipher->cipher,key,&(cipher->iv[0]));
395 EVP_DecryptUpdate(&ctx,data,&i,data,j);
396 o=EVP_DecryptFinal(&ctx,&(data[i]),&j);
397 EVP_CIPHER_CTX_cleanup(&ctx);
398 memset((char *)buf,0,sizeof(buf));
399 memset((char *)key,0,sizeof(key));
400 j+=i;
401 if (!o)
402 {
403 PEMerr(PEM_F_PEM_DO_HEADER,PEM_R_BAD_DECRYPT);
404 return(0);
405 }
406 *plen=j;
407 return(1);
408 }
409
410int PEM_get_EVP_CIPHER_INFO(header,cipher)
411char *header;
412EVP_CIPHER_INFO *cipher;
413 {
414 int o;
415 EVP_CIPHER *enc=NULL;
416 char *p,c;
417
418 cipher->cipher=NULL;
419 if ((header == NULL) || (*header == '\0') || (*header == '\n'))
420 return(1);
421 if (strncmp(header,"Proc-Type: ",11) != 0)
422 { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_PROC_TYPE); return(0); }
423 header+=11;
424 if (*header != '4') return(0); header++;
425 if (*header != ',') return(0); header++;
426 if (strncmp(header,"ENCRYPTED",9) != 0)
427 { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_ENCRYPTED); return(0); }
428 for (; (*header != '\n') && (*header != '\0'); header++)
429 ;
430 if (*header == '\0')
431 { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_SHORT_HEADER); return(0); }
432 header++;
433 if (strncmp(header,"DEK-Info: ",10) != 0)
434 { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_DEK_INFO); return(0); }
435 header+=10;
436
437 p=header;
438 for (;;)
439 {
440 c= *header;
441 if (!( ((c >= 'A') && (c <= 'Z')) || (c == '-') ||
442 ((c >= '0') && (c <= '9'))))
443 break;
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
462static int load_iv(fromp,to,num)
463unsigned char **fromp,*to;
464int num;
465 {
466 int v,i;
467 unsigned char *from;
468
469 from= *fromp;
470 for (i=0; i<num; i++) to[i]=0;
471 num*=2;
472 for (i=0; i<num; i++)
473 {
474 if ((*from >= '0') && (*from <= '9'))
475 v= *from-'0';
476 else if ((*from >= 'A') && (*from <= 'F'))
477 v= *from-'A'+10;
478 else if ((*from >= 'a') && (*from <= 'f'))
479 v= *from-'a'+10;
480 else
481 {
482 PEMerr(PEM_F_LOAD_IV,PEM_R_BAD_IV_CHARS);
483 return(0);
484 }
485 from++;
486 to[i/2]|=v<<(long)((!(i&1))*4);
487 }
488
489 *fromp=from;
490 return(1);
491 }
492
493#ifndef NO_FP_API
494int PEM_write(fp, name, header, data,len)
495FILE *fp;
496char *name;
497char *header;
498unsigned char *data;
499long len;
500 {
501 BIO *b;
502 int ret;
503
504 if ((b=BIO_new(BIO_s_file())) == NULL)
505 {
506 PEMerr(PEM_F_PEM_WRITE,ERR_R_BUF_LIB);
507 return(0);
508 }
509 BIO_set_fp(b,fp,BIO_NOCLOSE);
510 ret=PEM_write_bio(b, name, header, data,len);
511 BIO_free(b);
512 return(ret);
513 }
514#endif
515
516int PEM_write_bio(bp, name, header, data,len)
517BIO *bp;
518char *name;
519char *header;
520unsigned char *data;
521long len;
522 {
523 int nlen,n,i,j,outl;
524 unsigned char *buf;
525 EVP_ENCODE_CTX ctx;
526 int reason=ERR_R_BUF_LIB;
527
528 EVP_EncodeInit(&ctx);
529 nlen=strlen(name);
530
531 if ( (BIO_write(bp,"-----BEGIN ",11) != 11) ||
532 (BIO_write(bp,name,nlen) != nlen) ||
533 (BIO_write(bp,"-----\n",6) != 6))
534 goto err;
535
536 i=strlen(header);
537 if (i > 0)
538 {
539 if ( (BIO_write(bp,header,i) != i) ||
540 (BIO_write(bp,"\n",1) != 1))
541 goto err;
542 }
543
544 buf=(unsigned char *)Malloc(PEM_BUFSIZE*8);
545 if (buf == NULL)
546 {
547 reason=ERR_R_MALLOC_FAILURE;
548 goto err;
549 }
550
551 i=j=0;
552 while (len > 0)
553 {
554 n=(int)((len>(PEM_BUFSIZE*5))?(PEM_BUFSIZE*5):len);
555 EVP_EncodeUpdate(&ctx,buf,&outl,&(data[j]),n);
556 if ((outl) && (BIO_write(bp,(char *)buf,outl) != outl))
557 goto err;
558 i+=outl;
559 len-=n;
560 j+=n;
561 }
562 EVP_EncodeFinal(&ctx,buf,&outl);
563 if ((outl > 0) && (BIO_write(bp,(char *)buf,outl) != outl)) goto err;
564 Free(buf);
565 if ( (BIO_write(bp,"-----END ",9) != 9) ||
566 (BIO_write(bp,name,nlen) != nlen) ||
567 (BIO_write(bp,"-----\n",6) != 6))
568 goto err;
569 return(i+outl);
570err:
571 PEMerr(PEM_F_PEM_WRITE_BIO,reason);
572 return(0);
573 }
574
575#ifndef NO_FP_API
576int PEM_read(fp, name, header, data,len)
577FILE *fp;
578char **name;
579char **header;
580unsigned char **data;
581long *len;
582 {
583 BIO *b;
584 int ret;
585
586 if ((b=BIO_new(BIO_s_file())) == NULL)
587 {
588 PEMerr(PEM_F_PEM_READ,ERR_R_BUF_LIB);
589 return(0);
590 }
591 BIO_set_fp(b,fp,BIO_NOCLOSE);
592 ret=PEM_read_bio(b, name, header, data,len);
593 BIO_free(b);
594 return(ret);
595 }
596#endif
597
598int PEM_read_bio(bp, name, header, data, len)
599BIO *bp;
600char **name;
601char **header;
602unsigned char **data;
603long *len;
604 {
605 EVP_ENCODE_CTX ctx;
606 int end=0,i,k,bl=0,hl=0,nohead=0;
607 char buf[256];
608 BUF_MEM *nameB;
609 BUF_MEM *headerB;
610 BUF_MEM *dataB,*tmpB;
611
612 nameB=BUF_MEM_new();
613 headerB=BUF_MEM_new();
614 dataB=BUF_MEM_new();
615 if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL))
616 {
617 PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
618 return(0);
619 }
620
621 buf[254]='\0';
622 for (;;)
623 {
624 i=BIO_gets(bp,buf,254);
625
626 if (i <= 0)
627 {
628 PEMerr(PEM_F_PEM_READ_BIO,PEM_R_NO_START_LINE);
629 goto err;
630 }
631
632 while ((i >= 0) && (buf[i] <= ' ')) i--;
633 buf[++i]='\n'; buf[++i]='\0';
634
635 if (strncmp(buf,"-----BEGIN ",11) == 0)
636 {
637 i=strlen(&(buf[11]));
638
639 if (strncmp(&(buf[11+i-6]),"-----\n",6) != 0)
640 continue;
641 if (!BUF_MEM_grow(nameB,i+9))
642 {
643 PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
644 goto err;
645 }
646 strncpy(nameB->data,&(buf[11]),(unsigned int)i-6);
647 nameB->data[i-6]='\0';
648 break;
649 }
650 }
651 hl=0;
652 if (!BUF_MEM_grow(headerB,256))
653 { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
654 headerB->data[0]='\0';
655 for (;;)
656 {
657 i=BIO_gets(bp,buf,254);
658 if (i <= 0) break;
659
660 while ((i >= 0) && (buf[i] <= ' ')) i--;
661 buf[++i]='\n'; buf[++i]='\0';
662
663 if (buf[0] == '\n') break;
664 if (!BUF_MEM_grow(headerB,hl+i+9))
665 { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
666 if (strncmp(buf,"-----END ",9) == 0)
667 {
668 nohead=1;
669 break;
670 }
671 strncpy(&(headerB->data[hl]),buf,(unsigned int)i);
672 headerB->data[hl+i]='\0';
673 hl+=i;
674 }
675
676 bl=0;
677 if (!BUF_MEM_grow(dataB,1024))
678 { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
679 dataB->data[0]='\0';
680 if (!nohead)
681 {
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 (i != 65) end=1;
691 if (strncmp(buf,"-----END ",9) == 0)
692 break;
693 if (i > 65) break;
694 if (!BUF_MEM_grow(dataB,i+bl+9))
695 {
696 PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
697 goto err;
698 }
699 strncpy(&(dataB->data[bl]),buf,(unsigned int)i);
700 dataB->data[bl+i]='\0';
701 bl+=i;
702 if (end)
703 {
704 buf[0]='\0';
705 i=BIO_gets(bp,buf,254);
706 if (i <= 0) break;
707
708 while ((i >= 0) && (buf[i] <= ' ')) i--;
709 buf[++i]='\n'; buf[++i]='\0';
710
711 break;
712 }
713 }
714 }
715 else
716 {
717 tmpB=headerB;
718 headerB=dataB;
719 dataB=tmpB;
720 bl=hl;
721 }
722 i=strlen(nameB->data);
723 if ( (strncmp(buf,"-----END ",9) != 0) ||
724 (strncmp(nameB->data,&(buf[9]),(unsigned int)i) != 0) ||
725 (strncmp(&(buf[9+i]),"-----\n",6) != 0))
726 {
727 PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_END_LINE);
728 goto err;
729 }
730
731 EVP_DecodeInit(&ctx);
732 i=EVP_DecodeUpdate(&ctx,
733 (unsigned char *)dataB->data,&bl,
734 (unsigned char *)dataB->data,bl);
735 if (i < 0)
736 {
737 PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);
738 goto err;
739 }
740 i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k);
741 if (i < 0)
742 {
743 PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);
744 goto err;
745 }
746 bl+=k;
747
748 if (bl == 0) goto err;
749 *name=nameB->data;
750 *header=headerB->data;
751 *data=(unsigned char *)dataB->data;
752 *len=bl;
753 Free(nameB);
754 Free(headerB);
755 Free(dataB);
756 return(1);
757err:
758 BUF_MEM_free(nameB);
759 BUF_MEM_free(headerB);
760 BUF_MEM_free(dataB);
761 return(0);
762 }