os/ossrv/ssl/libcrypto/src/crypto/pem/pem_lib.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/* crypto/pem/pem_lib.c */
sl@0
     2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
sl@0
     3
 * All rights reserved.
sl@0
     4
 *
sl@0
     5
 * This package is an SSL implementation written
sl@0
     6
 * by Eric Young (eay@cryptsoft.com).
sl@0
     7
 * The implementation was written so as to conform with Netscapes SSL.
sl@0
     8
 * 
sl@0
     9
 * This library is free for commercial and non-commercial use as long as
sl@0
    10
 * the following conditions are aheared to.  The following conditions
sl@0
    11
 * apply to all code found in this distribution, be it the RC4, RSA,
sl@0
    12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
sl@0
    13
 * included with this distribution is covered by the same copyright terms
sl@0
    14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
sl@0
    15
 * 
sl@0
    16
 * Copyright remains Eric Young's, and as such any Copyright notices in
sl@0
    17
 * the code are not to be removed.
sl@0
    18
 * If this package is used in a product, Eric Young should be given attribution
sl@0
    19
 * as the author of the parts of the library used.
sl@0
    20
 * This can be in the form of a textual message at program startup or
sl@0
    21
 * in documentation (online or textual) provided with the package.
sl@0
    22
 * 
sl@0
    23
 * Redistribution and use in source and binary forms, with or without
sl@0
    24
 * modification, are permitted provided that the following conditions
sl@0
    25
 * are met:
sl@0
    26
 * 1. Redistributions of source code must retain the copyright
sl@0
    27
 *    notice, this list of conditions and the following disclaimer.
sl@0
    28
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    29
 *    notice, this list of conditions and the following disclaimer in the
sl@0
    30
 *    documentation and/or other materials provided with the distribution.
sl@0
    31
 * 3. All advertising materials mentioning features or use of this software
sl@0
    32
 *    must display the following acknowledgement:
sl@0
    33
 *    "This product includes cryptographic software written by
sl@0
    34
 *     Eric Young (eay@cryptsoft.com)"
sl@0
    35
 *    The word 'cryptographic' can be left out if the rouines from the library
sl@0
    36
 *    being used are not cryptographic related :-).
sl@0
    37
 * 4. If you include any Windows specific code (or a derivative thereof) from 
sl@0
    38
 *    the apps directory (application code) you must include an acknowledgement:
sl@0
    39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
sl@0
    40
 * 
sl@0
    41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
sl@0
    42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
sl@0
    44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
sl@0
    45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
sl@0
    46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
sl@0
    47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
sl@0
    49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
sl@0
    50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
sl@0
    51
 * SUCH DAMAGE.
sl@0
    52
 * 
sl@0
    53
 * The licence and distribution terms for any publically available version or
sl@0
    54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
sl@0
    55
 * copied and put under another distribution licence
sl@0
    56
 * [including the GNU Public Licence.]
sl@0
    57
 */
sl@0
    58
sl@0
    59
#include <stdio.h>
sl@0
    60
#include "cryptlib.h"
sl@0
    61
#include <openssl/buffer.h>
sl@0
    62
#include <openssl/objects.h>
sl@0
    63
#include <openssl/evp.h>
sl@0
    64
#include <openssl/rand.h>
sl@0
    65
#include <openssl/x509.h>
sl@0
    66
#include <openssl/pem.h>
sl@0
    67
#include <openssl/pkcs12.h>
sl@0
    68
#ifndef OPENSSL_NO_DES
sl@0
    69
#include <openssl/des.h>
sl@0
    70
#endif
sl@0
    71
sl@0
    72
const char PEM_version[]="PEM" OPENSSL_VERSION_PTEXT;
sl@0
    73
sl@0
    74
#define MIN_LENGTH	4
sl@0
    75
sl@0
    76
static int load_iv(char **fromp,unsigned char *to, int num);
sl@0
    77
static int check_pem(const char *nm, const char *name);
sl@0
    78
sl@0
    79
EXPORT_C int PEM_def_callback(char *buf, int num, int w, void *key)
sl@0
    80
	{
sl@0
    81
#ifdef OPENSSL_NO_FP_API
sl@0
    82
	/* We should not ever call the default callback routine from
sl@0
    83
	 * windows. */
sl@0
    84
	PEMerr(PEM_F_PEM_DEF_CALLBACK,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
sl@0
    85
	return(-1);
sl@0
    86
#else
sl@0
    87
	int i,j;
sl@0
    88
	const char *prompt;
sl@0
    89
	if(key) {
sl@0
    90
		i=strlen(key);
sl@0
    91
		i=(i > num)?num:i;
sl@0
    92
		memcpy(buf,key,i);
sl@0
    93
		return(i);
sl@0
    94
	}
sl@0
    95
sl@0
    96
	prompt=EVP_get_pw_prompt();
sl@0
    97
	if (prompt == NULL)
sl@0
    98
		prompt="Enter PEM pass phrase:";
sl@0
    99
sl@0
   100
	for (;;)
sl@0
   101
		{
sl@0
   102
		i=EVP_read_pw_string(buf,num,prompt,w);
sl@0
   103
		if (i != 0)
sl@0
   104
			{
sl@0
   105
			PEMerr(PEM_F_PEM_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD);
sl@0
   106
			memset(buf,0,(unsigned int)num);
sl@0
   107
			return(-1);
sl@0
   108
			}
sl@0
   109
		j=strlen(buf);
sl@0
   110
		if (j < MIN_LENGTH)
sl@0
   111
			{
sl@0
   112
			fprintf(stderr,"phrase is too short, needs to be at least %d chars\n",MIN_LENGTH);
sl@0
   113
			}
sl@0
   114
		else
sl@0
   115
			break;
sl@0
   116
		}
sl@0
   117
	return(j);
sl@0
   118
#endif
sl@0
   119
	}
sl@0
   120
sl@0
   121
EXPORT_C void PEM_proc_type(char *buf, int type)
sl@0
   122
	{
sl@0
   123
	const char *str;
sl@0
   124
sl@0
   125
	if (type == PEM_TYPE_ENCRYPTED)
sl@0
   126
		str="ENCRYPTED";
sl@0
   127
	else if (type == PEM_TYPE_MIC_CLEAR)
sl@0
   128
		str="MIC-CLEAR";
sl@0
   129
	else if (type == PEM_TYPE_MIC_ONLY)
sl@0
   130
		str="MIC-ONLY";
sl@0
   131
	else
sl@0
   132
		str="BAD-TYPE";
sl@0
   133
		
sl@0
   134
	BUF_strlcat(buf,"Proc-Type: 4,",PEM_BUFSIZE);
sl@0
   135
	BUF_strlcat(buf,str,PEM_BUFSIZE);
sl@0
   136
	BUF_strlcat(buf,"\n",PEM_BUFSIZE);
sl@0
   137
	}
sl@0
   138
sl@0
   139
EXPORT_C void PEM_dek_info(char *buf, const char *type, int len, char *str)
sl@0
   140
	{
sl@0
   141
	static const unsigned char map[17]="0123456789ABCDEF";
sl@0
   142
	long i;
sl@0
   143
	int j;
sl@0
   144
sl@0
   145
	BUF_strlcat(buf,"DEK-Info: ",PEM_BUFSIZE);
sl@0
   146
	BUF_strlcat(buf,type,PEM_BUFSIZE);
sl@0
   147
	BUF_strlcat(buf,",",PEM_BUFSIZE);
sl@0
   148
	j=strlen(buf);
sl@0
   149
	if (j + (len * 2) + 1 > PEM_BUFSIZE)
sl@0
   150
        	return;
sl@0
   151
	for (i=0; i<len; i++)
sl@0
   152
		{
sl@0
   153
		buf[j+i*2]  =map[(str[i]>>4)&0x0f];
sl@0
   154
		buf[j+i*2+1]=map[(str[i]   )&0x0f];
sl@0
   155
		}
sl@0
   156
	buf[j+i*2]='\n';
sl@0
   157
	buf[j+i*2+1]='\0';
sl@0
   158
	}
sl@0
   159
sl@0
   160
#ifndef OPENSSL_NO_FP_API
sl@0
   161
EXPORT_C void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x,
sl@0
   162
		    pem_password_cb *cb, void *u)
sl@0
   163
	{
sl@0
   164
        BIO *b;
sl@0
   165
        void *ret;
sl@0
   166
sl@0
   167
        if ((b=BIO_new(BIO_s_file())) == NULL)
sl@0
   168
		{
sl@0
   169
		PEMerr(PEM_F_PEM_ASN1_READ,ERR_R_BUF_LIB);
sl@0
   170
                return(0);
sl@0
   171
		}
sl@0
   172
        BIO_set_fp(b,fp,BIO_NOCLOSE);
sl@0
   173
        ret=PEM_ASN1_read_bio(d2i,name,b,x,cb,u);
sl@0
   174
        BIO_free(b);
sl@0
   175
        return(ret);
sl@0
   176
	}
sl@0
   177
#endif
sl@0
   178
sl@0
   179
static int check_pem(const char *nm, const char *name)
sl@0
   180
{
sl@0
   181
	/* Normal matching nm and name */
sl@0
   182
	if (!strcmp(nm,name)) return 1;
sl@0
   183
sl@0
   184
	/* Make PEM_STRING_EVP_PKEY match any private key */
sl@0
   185
sl@0
   186
	if(!strcmp(nm,PEM_STRING_PKCS8) &&
sl@0
   187
		!strcmp(name,PEM_STRING_EVP_PKEY)) return 1;
sl@0
   188
sl@0
   189
	if(!strcmp(nm,PEM_STRING_PKCS8INF) &&
sl@0
   190
		 !strcmp(name,PEM_STRING_EVP_PKEY)) return 1;
sl@0
   191
sl@0
   192
	if(!strcmp(nm,PEM_STRING_RSA) &&
sl@0
   193
		!strcmp(name,PEM_STRING_EVP_PKEY)) return 1;
sl@0
   194
sl@0
   195
	if(!strcmp(nm,PEM_STRING_DSA) &&
sl@0
   196
		 !strcmp(name,PEM_STRING_EVP_PKEY)) return 1;
sl@0
   197
sl@0
   198
 	if(!strcmp(nm,PEM_STRING_ECPRIVATEKEY) &&
sl@0
   199
 		 !strcmp(name,PEM_STRING_EVP_PKEY)) return 1;
sl@0
   200
	/* Permit older strings */
sl@0
   201
sl@0
   202
	if(!strcmp(nm,PEM_STRING_X509_OLD) &&
sl@0
   203
		!strcmp(name,PEM_STRING_X509)) return 1;
sl@0
   204
sl@0
   205
	if(!strcmp(nm,PEM_STRING_X509_REQ_OLD) &&
sl@0
   206
		!strcmp(name,PEM_STRING_X509_REQ)) return 1;
sl@0
   207
sl@0
   208
	/* Allow normal certs to be read as trusted certs */
sl@0
   209
	if(!strcmp(nm,PEM_STRING_X509) &&
sl@0
   210
		!strcmp(name,PEM_STRING_X509_TRUSTED)) return 1;
sl@0
   211
sl@0
   212
	if(!strcmp(nm,PEM_STRING_X509_OLD) &&
sl@0
   213
		!strcmp(name,PEM_STRING_X509_TRUSTED)) return 1;
sl@0
   214
sl@0
   215
	/* Some CAs use PKCS#7 with CERTIFICATE headers */
sl@0
   216
	if(!strcmp(nm, PEM_STRING_X509) &&
sl@0
   217
		!strcmp(name, PEM_STRING_PKCS7)) return 1;
sl@0
   218
sl@0
   219
	return 0;
sl@0
   220
}
sl@0
   221
sl@0
   222
EXPORT_C int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp,
sl@0
   223
	     pem_password_cb *cb, void *u)
sl@0
   224
	{
sl@0
   225
	EVP_CIPHER_INFO cipher;
sl@0
   226
	char *nm=NULL,*header=NULL;
sl@0
   227
	unsigned char *data=NULL;
sl@0
   228
	long len;
sl@0
   229
	int ret = 0;
sl@0
   230
sl@0
   231
	for (;;)
sl@0
   232
		{
sl@0
   233
		if (!PEM_read_bio(bp,&nm,&header,&data,&len)) {
sl@0
   234
			if(ERR_GET_REASON(ERR_peek_error()) ==
sl@0
   235
				PEM_R_NO_START_LINE)
sl@0
   236
				ERR_add_error_data(2, "Expecting: ", name);
sl@0
   237
			return 0;
sl@0
   238
		}
sl@0
   239
		if(check_pem(nm, name)) break;
sl@0
   240
		OPENSSL_free(nm);
sl@0
   241
		OPENSSL_free(header);
sl@0
   242
		OPENSSL_free(data);
sl@0
   243
		}
sl@0
   244
	if (!PEM_get_EVP_CIPHER_INFO(header,&cipher)) goto err;
sl@0
   245
	if (!PEM_do_header(&cipher,data,&len,cb,u)) goto err;
sl@0
   246
sl@0
   247
	*pdata = data;
sl@0
   248
	*plen = len;
sl@0
   249
sl@0
   250
	if (pnm)
sl@0
   251
		*pnm = nm;
sl@0
   252
sl@0
   253
	ret = 1;
sl@0
   254
sl@0
   255
err:
sl@0
   256
	if (!ret || !pnm) OPENSSL_free(nm);
sl@0
   257
	OPENSSL_free(header);
sl@0
   258
	if (!ret) OPENSSL_free(data);
sl@0
   259
	return ret;
sl@0
   260
	}
sl@0
   261
sl@0
   262
#ifndef OPENSSL_NO_FP_API
sl@0
   263
EXPORT_C int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp,
sl@0
   264
		   char *x, const EVP_CIPHER *enc, unsigned char *kstr,
sl@0
   265
		   int klen, pem_password_cb *callback, void *u)
sl@0
   266
        {
sl@0
   267
        BIO *b;
sl@0
   268
        int ret;
sl@0
   269
sl@0
   270
        if ((b=BIO_new(BIO_s_file())) == NULL)
sl@0
   271
		{
sl@0
   272
		PEMerr(PEM_F_PEM_ASN1_WRITE,ERR_R_BUF_LIB);
sl@0
   273
                return(0);
sl@0
   274
		}
sl@0
   275
        BIO_set_fp(b,fp,BIO_NOCLOSE);
sl@0
   276
        ret=PEM_ASN1_write_bio(i2d,name,b,x,enc,kstr,klen,callback,u);
sl@0
   277
        BIO_free(b);
sl@0
   278
        return(ret);
sl@0
   279
        }
sl@0
   280
#endif
sl@0
   281
sl@0
   282
EXPORT_C int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
sl@0
   283
		       char *x, const EVP_CIPHER *enc, unsigned char *kstr,
sl@0
   284
		       int klen, pem_password_cb *callback, void *u)
sl@0
   285
	{
sl@0
   286
	EVP_CIPHER_CTX ctx;
sl@0
   287
	int dsize=0,i,j,ret=0;
sl@0
   288
	unsigned char *p,*data=NULL;
sl@0
   289
	const char *objstr=NULL;
sl@0
   290
	char buf[PEM_BUFSIZE];
sl@0
   291
	unsigned char key[EVP_MAX_KEY_LENGTH];
sl@0
   292
	unsigned char iv[EVP_MAX_IV_LENGTH];
sl@0
   293
	
sl@0
   294
	if (enc != NULL)
sl@0
   295
		{
sl@0
   296
		objstr=OBJ_nid2sn(EVP_CIPHER_nid(enc));
sl@0
   297
		if (objstr == NULL)
sl@0
   298
			{
sl@0
   299
			PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_UNSUPPORTED_CIPHER);
sl@0
   300
			goto err;
sl@0
   301
			}
sl@0
   302
		}
sl@0
   303
sl@0
   304
	if ((dsize=i2d(x,NULL)) < 0)
sl@0
   305
		{
sl@0
   306
		PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_ASN1_LIB);
sl@0
   307
		dsize=0;
sl@0
   308
		goto err;
sl@0
   309
		}
sl@0
   310
	/* dzise + 8 bytes are needed */
sl@0
   311
	/* actually it needs the cipher block size extra... */
sl@0
   312
	data=(unsigned char *)OPENSSL_malloc((unsigned int)dsize+20);
sl@0
   313
	if (data == NULL)
sl@0
   314
		{
sl@0
   315
		PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_MALLOC_FAILURE);
sl@0
   316
		goto err;
sl@0
   317
		}
sl@0
   318
	p=data;
sl@0
   319
	i=i2d(x,&p);
sl@0
   320
sl@0
   321
	if (enc != NULL)
sl@0
   322
		{
sl@0
   323
		if (kstr == NULL)
sl@0
   324
			{
sl@0
   325
			if (callback == NULL)
sl@0
   326
				klen=PEM_def_callback(buf,PEM_BUFSIZE,1,u);
sl@0
   327
			else
sl@0
   328
				klen=(*callback)(buf,PEM_BUFSIZE,1,u);
sl@0
   329
			if (klen <= 0)
sl@0
   330
				{
sl@0
   331
				PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_READ_KEY);
sl@0
   332
				goto err;
sl@0
   333
				}
sl@0
   334
#ifdef CHARSET_EBCDIC
sl@0
   335
			/* Convert the pass phrase from EBCDIC */
sl@0
   336
			ebcdic2ascii(buf, buf, klen);
sl@0
   337
#endif
sl@0
   338
			kstr=(unsigned char *)buf;
sl@0
   339
			}
sl@0
   340
		RAND_add(data,i,0);/* put in the RSA key. */
sl@0
   341
		OPENSSL_assert(enc->iv_len <= (int)sizeof(iv));
sl@0
   342
		if (RAND_pseudo_bytes(iv,enc->iv_len) < 0) /* Generate a salt */
sl@0
   343
			goto err;
sl@0
   344
		/* The 'iv' is used as the iv and as a salt.  It is
sl@0
   345
		 * NOT taken from the BytesToKey function */
sl@0
   346
		EVP_BytesToKey(enc,EVP_md5(),iv,kstr,klen,1,key,NULL);
sl@0
   347
sl@0
   348
		if (kstr == (unsigned char *)buf) OPENSSL_cleanse(buf,PEM_BUFSIZE);
sl@0
   349
sl@0
   350
		OPENSSL_assert(strlen(objstr)+23+2*enc->iv_len+13 <= sizeof buf);
sl@0
   351
sl@0
   352
		buf[0]='\0';
sl@0
   353
		PEM_proc_type(buf,PEM_TYPE_ENCRYPTED);
sl@0
   354
		PEM_dek_info(buf,objstr,enc->iv_len,(char *)iv);
sl@0
   355
		/* k=strlen(buf); */
sl@0
   356
sl@0
   357
		EVP_CIPHER_CTX_init(&ctx);
sl@0
   358
		EVP_EncryptInit_ex(&ctx,enc,NULL,key,iv);
sl@0
   359
		EVP_EncryptUpdate(&ctx,data,&j,data,i);
sl@0
   360
		EVP_EncryptFinal_ex(&ctx,&(data[j]),&i);
sl@0
   361
		EVP_CIPHER_CTX_cleanup(&ctx);
sl@0
   362
		i+=j;
sl@0
   363
		ret=1;
sl@0
   364
		}
sl@0
   365
	else
sl@0
   366
		{
sl@0
   367
		ret=1;
sl@0
   368
		buf[0]='\0';
sl@0
   369
		}
sl@0
   370
	i=PEM_write_bio(bp,name,buf,data,i);
sl@0
   371
	if (i <= 0) ret=0;
sl@0
   372
err:
sl@0
   373
	OPENSSL_cleanse(key,sizeof(key));
sl@0
   374
	OPENSSL_cleanse(iv,sizeof(iv));
sl@0
   375
	OPENSSL_cleanse((char *)&ctx,sizeof(ctx));
sl@0
   376
	OPENSSL_cleanse(buf,PEM_BUFSIZE);
sl@0
   377
	if (data != NULL)
sl@0
   378
		{
sl@0
   379
		OPENSSL_cleanse(data,(unsigned int)dsize);
sl@0
   380
		OPENSSL_free(data);
sl@0
   381
		}
sl@0
   382
	return(ret);
sl@0
   383
	}
sl@0
   384
sl@0
   385
EXPORT_C int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen,
sl@0
   386
	     pem_password_cb *callback,void *u)
sl@0
   387
	{
sl@0
   388
	int i,j,o,klen;
sl@0
   389
	long len;
sl@0
   390
	EVP_CIPHER_CTX ctx;
sl@0
   391
	unsigned char key[EVP_MAX_KEY_LENGTH];
sl@0
   392
	char buf[PEM_BUFSIZE];
sl@0
   393
sl@0
   394
	len= *plen;
sl@0
   395
sl@0
   396
	if (cipher->cipher == NULL) return(1);
sl@0
   397
	if (callback == NULL)
sl@0
   398
		klen=PEM_def_callback(buf,PEM_BUFSIZE,0,u);
sl@0
   399
	else
sl@0
   400
		klen=callback(buf,PEM_BUFSIZE,0,u);
sl@0
   401
	if (klen <= 0)
sl@0
   402
		{
sl@0
   403
		PEMerr(PEM_F_PEM_DO_HEADER,PEM_R_BAD_PASSWORD_READ);
sl@0
   404
		return(0);
sl@0
   405
		}
sl@0
   406
#ifdef CHARSET_EBCDIC
sl@0
   407
	/* Convert the pass phrase from EBCDIC */
sl@0
   408
	ebcdic2ascii(buf, buf, klen);
sl@0
   409
#endif
sl@0
   410
sl@0
   411
	EVP_BytesToKey(cipher->cipher,EVP_md5(),&(cipher->iv[0]),
sl@0
   412
		(unsigned char *)buf,klen,1,key,NULL);
sl@0
   413
sl@0
   414
	j=(int)len;
sl@0
   415
	EVP_CIPHER_CTX_init(&ctx);
sl@0
   416
	EVP_DecryptInit_ex(&ctx,cipher->cipher,NULL, key,&(cipher->iv[0]));
sl@0
   417
	EVP_DecryptUpdate(&ctx,data,&i,data,j);
sl@0
   418
	o=EVP_DecryptFinal_ex(&ctx,&(data[i]),&j);
sl@0
   419
	EVP_CIPHER_CTX_cleanup(&ctx);
sl@0
   420
	OPENSSL_cleanse((char *)buf,sizeof(buf));
sl@0
   421
	OPENSSL_cleanse((char *)key,sizeof(key));
sl@0
   422
	j+=i;
sl@0
   423
	if (!o)
sl@0
   424
		{
sl@0
   425
		PEMerr(PEM_F_PEM_DO_HEADER,PEM_R_BAD_DECRYPT);
sl@0
   426
		return(0);
sl@0
   427
		}
sl@0
   428
	*plen=j;
sl@0
   429
	return(1);
sl@0
   430
	}
sl@0
   431
sl@0
   432
EXPORT_C int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher)
sl@0
   433
	{
sl@0
   434
	int o;
sl@0
   435
	const EVP_CIPHER *enc=NULL;
sl@0
   436
	char *p,c;
sl@0
   437
	char **header_pp = &header;
sl@0
   438
sl@0
   439
	cipher->cipher=NULL;
sl@0
   440
	if ((header == NULL) || (*header == '\0') || (*header == '\n'))
sl@0
   441
		return(1);
sl@0
   442
	if (strncmp(header,"Proc-Type: ",11) != 0)
sl@0
   443
		{ PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_PROC_TYPE); return(0); }
sl@0
   444
	header+=11;
sl@0
   445
	if (*header != '4') return(0); header++;
sl@0
   446
	if (*header != ',') return(0); header++;
sl@0
   447
	if (strncmp(header,"ENCRYPTED",9) != 0)
sl@0
   448
		{ PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_ENCRYPTED); return(0); }
sl@0
   449
	for (; (*header != '\n') && (*header != '\0'); header++)
sl@0
   450
		;
sl@0
   451
	if (*header == '\0')
sl@0
   452
		{ PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_SHORT_HEADER); return(0); }
sl@0
   453
	header++;
sl@0
   454
	if (strncmp(header,"DEK-Info: ",10) != 0)
sl@0
   455
		{ PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_DEK_INFO); return(0); }
sl@0
   456
	header+=10;
sl@0
   457
sl@0
   458
	p=header;
sl@0
   459
	for (;;)
sl@0
   460
		{
sl@0
   461
		c= *header;
sl@0
   462
#ifndef CHARSET_EBCDIC
sl@0
   463
		if (!(	((c >= 'A') && (c <= 'Z')) || (c == '-') ||
sl@0
   464
			((c >= '0') && (c <= '9'))))
sl@0
   465
			break;
sl@0
   466
#else
sl@0
   467
		if (!(	isupper(c) || (c == '-') ||
sl@0
   468
			isdigit(c)))
sl@0
   469
			break;
sl@0
   470
#endif
sl@0
   471
		header++;
sl@0
   472
		}
sl@0
   473
	*header='\0';
sl@0
   474
	o=OBJ_sn2nid(p);
sl@0
   475
	cipher->cipher=enc=EVP_get_cipherbyname(p);
sl@0
   476
	*header=c;
sl@0
   477
	header++;
sl@0
   478
sl@0
   479
	if (enc == NULL)
sl@0
   480
		{
sl@0
   481
		PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_UNSUPPORTED_ENCRYPTION);
sl@0
   482
		return(0);
sl@0
   483
		}
sl@0
   484
	if (!load_iv(header_pp,&(cipher->iv[0]),enc->iv_len))
sl@0
   485
		return(0);
sl@0
   486
sl@0
   487
	return(1);
sl@0
   488
	}
sl@0
   489
sl@0
   490
static int load_iv(char **fromp, unsigned char *to, int num)
sl@0
   491
	{
sl@0
   492
	int v,i;
sl@0
   493
	char *from;
sl@0
   494
sl@0
   495
	from= *fromp;
sl@0
   496
	for (i=0; i<num; i++) to[i]=0;
sl@0
   497
	num*=2;
sl@0
   498
	for (i=0; i<num; i++)
sl@0
   499
		{
sl@0
   500
		if ((*from >= '0') && (*from <= '9'))
sl@0
   501
			v= *from-'0';
sl@0
   502
		else if ((*from >= 'A') && (*from <= 'F'))
sl@0
   503
			v= *from-'A'+10;
sl@0
   504
		else if ((*from >= 'a') && (*from <= 'f'))
sl@0
   505
			v= *from-'a'+10;
sl@0
   506
		else
sl@0
   507
			{
sl@0
   508
			PEMerr(PEM_F_LOAD_IV,PEM_R_BAD_IV_CHARS);
sl@0
   509
			return(0);
sl@0
   510
			}
sl@0
   511
		from++;
sl@0
   512
		to[i/2]|=v<<(long)((!(i&1))*4);
sl@0
   513
		}
sl@0
   514
sl@0
   515
	*fromp=from;
sl@0
   516
	return(1);
sl@0
   517
	}
sl@0
   518
sl@0
   519
#ifndef OPENSSL_NO_FP_API
sl@0
   520
EXPORT_C int PEM_write(FILE *fp, char *name, char *header, unsigned char *data,
sl@0
   521
	     long len)
sl@0
   522
        {
sl@0
   523
        BIO *b;
sl@0
   524
        int ret;
sl@0
   525
sl@0
   526
        if ((b=BIO_new(BIO_s_file())) == NULL)
sl@0
   527
		{
sl@0
   528
		PEMerr(PEM_F_PEM_WRITE,ERR_R_BUF_LIB);
sl@0
   529
                return(0);
sl@0
   530
		}
sl@0
   531
        BIO_set_fp(b,fp,BIO_NOCLOSE);
sl@0
   532
        ret=PEM_write_bio(b, name, header, data,len);
sl@0
   533
        BIO_free(b);
sl@0
   534
        return(ret);
sl@0
   535
        }
sl@0
   536
#endif
sl@0
   537
sl@0
   538
EXPORT_C int PEM_write_bio(BIO *bp, const char *name, char *header, unsigned char *data,
sl@0
   539
	     long len)
sl@0
   540
	{
sl@0
   541
	int nlen,n,i,j,outl;
sl@0
   542
	unsigned char *buf = NULL;
sl@0
   543
	EVP_ENCODE_CTX ctx;
sl@0
   544
	int reason=ERR_R_BUF_LIB;
sl@0
   545
	
sl@0
   546
	EVP_EncodeInit(&ctx);
sl@0
   547
	nlen=strlen(name);
sl@0
   548
sl@0
   549
	if (	(BIO_write(bp,"-----BEGIN ",11) != 11) ||
sl@0
   550
		(BIO_write(bp,name,nlen) != nlen) ||
sl@0
   551
		(BIO_write(bp,"-----\n",6) != 6))
sl@0
   552
		goto err;
sl@0
   553
		
sl@0
   554
	i=strlen(header);
sl@0
   555
	if (i > 0)
sl@0
   556
		{
sl@0
   557
		if (	(BIO_write(bp,header,i) != i) ||
sl@0
   558
			(BIO_write(bp,"\n",1) != 1))
sl@0
   559
			goto err;
sl@0
   560
		}
sl@0
   561
sl@0
   562
	buf = OPENSSL_malloc(PEM_BUFSIZE*8);
sl@0
   563
	if (buf == NULL)
sl@0
   564
		{
sl@0
   565
		reason=ERR_R_MALLOC_FAILURE;
sl@0
   566
		goto err;
sl@0
   567
		}
sl@0
   568
sl@0
   569
	i=j=0;
sl@0
   570
	while (len > 0)
sl@0
   571
		{
sl@0
   572
		n=(int)((len>(PEM_BUFSIZE*5))?(PEM_BUFSIZE*5):len);
sl@0
   573
		EVP_EncodeUpdate(&ctx,buf,&outl,&(data[j]),n);
sl@0
   574
		if ((outl) && (BIO_write(bp,(char *)buf,outl) != outl))
sl@0
   575
			goto err;
sl@0
   576
		i+=outl;
sl@0
   577
		len-=n;
sl@0
   578
		j+=n;
sl@0
   579
		}
sl@0
   580
	EVP_EncodeFinal(&ctx,buf,&outl);
sl@0
   581
	if ((outl > 0) && (BIO_write(bp,(char *)buf,outl) != outl)) goto err;
sl@0
   582
	OPENSSL_cleanse(buf, PEM_BUFSIZE*8);
sl@0
   583
	OPENSSL_free(buf);
sl@0
   584
	buf = NULL;
sl@0
   585
	if (	(BIO_write(bp,"-----END ",9) != 9) ||
sl@0
   586
		(BIO_write(bp,name,nlen) != nlen) ||
sl@0
   587
		(BIO_write(bp,"-----\n",6) != 6))
sl@0
   588
		goto err;
sl@0
   589
	return(i+outl);
sl@0
   590
err:
sl@0
   591
	if (buf) {
sl@0
   592
		OPENSSL_cleanse(buf, PEM_BUFSIZE*8);
sl@0
   593
		OPENSSL_free(buf);
sl@0
   594
	}
sl@0
   595
	PEMerr(PEM_F_PEM_WRITE_BIO,reason);
sl@0
   596
	return(0);
sl@0
   597
	}
sl@0
   598
sl@0
   599
#ifndef OPENSSL_NO_FP_API
sl@0
   600
EXPORT_C int PEM_read(FILE *fp, char **name, char **header, unsigned char **data,
sl@0
   601
	     long *len)
sl@0
   602
        {
sl@0
   603
        BIO *b;
sl@0
   604
        int ret;
sl@0
   605
sl@0
   606
        if ((b=BIO_new(BIO_s_file())) == NULL)
sl@0
   607
		{
sl@0
   608
		PEMerr(PEM_F_PEM_READ,ERR_R_BUF_LIB);
sl@0
   609
                return(0);
sl@0
   610
		}
sl@0
   611
        BIO_set_fp(b,fp,BIO_NOCLOSE);
sl@0
   612
        ret=PEM_read_bio(b, name, header, data,len);
sl@0
   613
        BIO_free(b);
sl@0
   614
        return(ret);
sl@0
   615
        }
sl@0
   616
#endif
sl@0
   617
sl@0
   618
EXPORT_C int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
sl@0
   619
	     long *len)
sl@0
   620
	{
sl@0
   621
	EVP_ENCODE_CTX ctx;
sl@0
   622
	int end=0,i,k,bl=0,hl=0,nohead=0;
sl@0
   623
	char buf[256];
sl@0
   624
	BUF_MEM *nameB;
sl@0
   625
	BUF_MEM *headerB;
sl@0
   626
	BUF_MEM *dataB,*tmpB;
sl@0
   627
	
sl@0
   628
	nameB=BUF_MEM_new();
sl@0
   629
	headerB=BUF_MEM_new();
sl@0
   630
	dataB=BUF_MEM_new();
sl@0
   631
	if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL))
sl@0
   632
		{
sl@0
   633
		BUF_MEM_free(nameB);
sl@0
   634
		BUF_MEM_free(headerB);
sl@0
   635
		BUF_MEM_free(dataB);
sl@0
   636
		PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
sl@0
   637
		return(0);
sl@0
   638
		}
sl@0
   639
sl@0
   640
	buf[254]='\0';
sl@0
   641
	for (;;)
sl@0
   642
		{
sl@0
   643
		i=BIO_gets(bp,buf,254);
sl@0
   644
sl@0
   645
		if (i <= 0)
sl@0
   646
			{
sl@0
   647
			PEMerr(PEM_F_PEM_READ_BIO,PEM_R_NO_START_LINE);
sl@0
   648
			goto err;
sl@0
   649
			}
sl@0
   650
sl@0
   651
		while ((i >= 0) && (buf[i] <= ' ')) i--;
sl@0
   652
		buf[++i]='\n'; buf[++i]='\0';
sl@0
   653
sl@0
   654
		if (strncmp(buf,"-----BEGIN ",11) == 0)
sl@0
   655
			{
sl@0
   656
			i=strlen(&(buf[11]));
sl@0
   657
sl@0
   658
			if (strncmp(&(buf[11+i-6]),"-----\n",6) != 0)
sl@0
   659
				continue;
sl@0
   660
			if (!BUF_MEM_grow(nameB,i+9))
sl@0
   661
				{
sl@0
   662
				PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
sl@0
   663
				goto err;
sl@0
   664
				}
sl@0
   665
			memcpy(nameB->data,&(buf[11]),i-6);
sl@0
   666
			nameB->data[i-6]='\0';
sl@0
   667
			break;
sl@0
   668
			}
sl@0
   669
		}
sl@0
   670
	hl=0;
sl@0
   671
	if (!BUF_MEM_grow(headerB,256))
sl@0
   672
		{ PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
sl@0
   673
	headerB->data[0]='\0';
sl@0
   674
	for (;;)
sl@0
   675
		{
sl@0
   676
		i=BIO_gets(bp,buf,254);
sl@0
   677
		if (i <= 0) break;
sl@0
   678
sl@0
   679
		while ((i >= 0) && (buf[i] <= ' ')) i--;
sl@0
   680
		buf[++i]='\n'; buf[++i]='\0';
sl@0
   681
sl@0
   682
		if (buf[0] == '\n') break;
sl@0
   683
		if (!BUF_MEM_grow(headerB,hl+i+9))
sl@0
   684
			{ PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
sl@0
   685
		if (strncmp(buf,"-----END ",9) == 0)
sl@0
   686
			{
sl@0
   687
			nohead=1;
sl@0
   688
			break;
sl@0
   689
			}
sl@0
   690
		memcpy(&(headerB->data[hl]),buf,i);
sl@0
   691
		headerB->data[hl+i]='\0';
sl@0
   692
		hl+=i;
sl@0
   693
		}
sl@0
   694
sl@0
   695
	bl=0;
sl@0
   696
	if (!BUF_MEM_grow(dataB,1024))
sl@0
   697
		{ PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
sl@0
   698
	dataB->data[0]='\0';
sl@0
   699
	if (!nohead)
sl@0
   700
		{
sl@0
   701
		for (;;)
sl@0
   702
			{
sl@0
   703
			i=BIO_gets(bp,buf,254);
sl@0
   704
			if (i <= 0) break;
sl@0
   705
sl@0
   706
			while ((i >= 0) && (buf[i] <= ' ')) i--;
sl@0
   707
			buf[++i]='\n'; buf[++i]='\0';
sl@0
   708
sl@0
   709
			if (i != 65) end=1;
sl@0
   710
			if (strncmp(buf,"-----END ",9) == 0)
sl@0
   711
				break;
sl@0
   712
			if (i > 65) break;
sl@0
   713
			if (!BUF_MEM_grow_clean(dataB,i+bl+9))
sl@0
   714
				{
sl@0
   715
				PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
sl@0
   716
				goto err;
sl@0
   717
				}
sl@0
   718
			memcpy(&(dataB->data[bl]),buf,i);
sl@0
   719
			dataB->data[bl+i]='\0';
sl@0
   720
			bl+=i;
sl@0
   721
			if (end)
sl@0
   722
				{
sl@0
   723
				buf[0]='\0';
sl@0
   724
				i=BIO_gets(bp,buf,254);
sl@0
   725
				if (i <= 0) break;
sl@0
   726
sl@0
   727
				while ((i >= 0) && (buf[i] <= ' ')) i--;
sl@0
   728
				buf[++i]='\n'; buf[++i]='\0';
sl@0
   729
sl@0
   730
				break;
sl@0
   731
				}
sl@0
   732
			}
sl@0
   733
		}
sl@0
   734
	else
sl@0
   735
		{
sl@0
   736
		tmpB=headerB;
sl@0
   737
		headerB=dataB;
sl@0
   738
		dataB=tmpB;
sl@0
   739
		bl=hl;
sl@0
   740
		}
sl@0
   741
	i=strlen(nameB->data);
sl@0
   742
	if (	(strncmp(buf,"-----END ",9) != 0) ||
sl@0
   743
		(strncmp(nameB->data,&(buf[9]),i) != 0) ||
sl@0
   744
		(strncmp(&(buf[9+i]),"-----\n",6) != 0))
sl@0
   745
		{
sl@0
   746
		PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_END_LINE);
sl@0
   747
		goto err;
sl@0
   748
		}
sl@0
   749
sl@0
   750
	EVP_DecodeInit(&ctx);
sl@0
   751
	i=EVP_DecodeUpdate(&ctx,
sl@0
   752
		(unsigned char *)dataB->data,&bl,
sl@0
   753
		(unsigned char *)dataB->data,bl);
sl@0
   754
	if (i < 0)
sl@0
   755
		{
sl@0
   756
		PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);
sl@0
   757
		goto err;
sl@0
   758
		}
sl@0
   759
	i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k);
sl@0
   760
	if (i < 0)
sl@0
   761
		{
sl@0
   762
		PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);
sl@0
   763
		goto err;
sl@0
   764
		}
sl@0
   765
	bl+=k;
sl@0
   766
sl@0
   767
	if (bl == 0) goto err;
sl@0
   768
	*name=nameB->data;
sl@0
   769
	*header=headerB->data;
sl@0
   770
	*data=(unsigned char *)dataB->data;
sl@0
   771
	*len=bl;
sl@0
   772
	OPENSSL_free(nameB);
sl@0
   773
	OPENSSL_free(headerB);
sl@0
   774
	OPENSSL_free(dataB);
sl@0
   775
	return(1);
sl@0
   776
err:
sl@0
   777
	BUF_MEM_free(nameB);
sl@0
   778
	BUF_MEM_free(headerB);
sl@0
   779
	BUF_MEM_free(dataB);
sl@0
   780
	return(0);
sl@0
   781
	}