155714Skris/* crypto/pem/pem_lib.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 855714Skris * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1555714Skris * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 2255714Skris * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4055714Skris * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 5255714Skris * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 60238405Sjkim#include <ctype.h> 6155714Skris#include "cryptlib.h" 6255714Skris#include <openssl/buffer.h> 6355714Skris#include <openssl/objects.h> 6455714Skris#include <openssl/evp.h> 6555714Skris#include <openssl/rand.h> 6655714Skris#include <openssl/x509.h> 6755714Skris#include <openssl/pem.h> 6855714Skris#include <openssl/pkcs12.h> 69238405Sjkim#include "asn1_locl.h" 70109998Smarkm#ifndef OPENSSL_NO_DES 7155714Skris#include <openssl/des.h> 7255714Skris#endif 73238405Sjkim#ifndef OPENSSL_NO_ENGINE 74238405Sjkim#include <openssl/engine.h> 75238405Sjkim#endif 7655714Skris 77167612Ssimonconst char PEM_version[]="PEM" OPENSSL_VERSION_PTEXT; 7855714Skris 7955714Skris#define MIN_LENGTH 4 8055714Skris 81160814Ssimonstatic int load_iv(char **fromp,unsigned char *to, int num); 8259191Skrisstatic int check_pem(const char *nm, const char *name); 83238405Sjkimint pem_check_suffix(const char *pem_str, const char *suffix); 8455714Skris 85109998Smarkmint PEM_def_callback(char *buf, int num, int w, void *key) 8655714Skris { 87109998Smarkm#ifdef OPENSSL_NO_FP_API 8855714Skris /* We should not ever call the default callback routine from 8955714Skris * windows. */ 90160814Ssimon PEMerr(PEM_F_PEM_DEF_CALLBACK,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 9155714Skris return(-1); 9255714Skris#else 9355714Skris int i,j; 9455714Skris const char *prompt; 9559191Skris if(key) { 9659191Skris i=strlen(key); 9759191Skris i=(i > num)?num:i; 9859191Skris memcpy(buf,key,i); 9959191Skris return(i); 10059191Skris } 10155714Skris 10255714Skris prompt=EVP_get_pw_prompt(); 10355714Skris if (prompt == NULL) 10455714Skris prompt="Enter PEM pass phrase:"; 10555714Skris 10655714Skris for (;;) 10755714Skris { 108238405Sjkim i=EVP_read_pw_string_min(buf,MIN_LENGTH,num,prompt,w); 10955714Skris if (i != 0) 11055714Skris { 111160814Ssimon PEMerr(PEM_F_PEM_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD); 11255714Skris memset(buf,0,(unsigned int)num); 11355714Skris return(-1); 11455714Skris } 11555714Skris j=strlen(buf); 11655714Skris if (j < MIN_LENGTH) 11755714Skris { 11855714Skris fprintf(stderr,"phrase is too short, needs to be at least %d chars\n",MIN_LENGTH); 11955714Skris } 12055714Skris else 12155714Skris break; 12255714Skris } 12355714Skris return(j); 12455714Skris#endif 12555714Skris } 12655714Skris 12755714Skrisvoid PEM_proc_type(char *buf, int type) 12855714Skris { 12955714Skris const char *str; 13055714Skris 13155714Skris if (type == PEM_TYPE_ENCRYPTED) 13255714Skris str="ENCRYPTED"; 13355714Skris else if (type == PEM_TYPE_MIC_CLEAR) 13455714Skris str="MIC-CLEAR"; 13555714Skris else if (type == PEM_TYPE_MIC_ONLY) 13655714Skris str="MIC-ONLY"; 13755714Skris else 13855714Skris str="BAD-TYPE"; 13955714Skris 140127128Snectar BUF_strlcat(buf,"Proc-Type: 4,",PEM_BUFSIZE); 141127128Snectar BUF_strlcat(buf,str,PEM_BUFSIZE); 142127128Snectar BUF_strlcat(buf,"\n",PEM_BUFSIZE); 14355714Skris } 14455714Skris 14555714Skrisvoid PEM_dek_info(char *buf, const char *type, int len, char *str) 14655714Skris { 147109998Smarkm static const unsigned char map[17]="0123456789ABCDEF"; 14855714Skris long i; 14955714Skris int j; 15055714Skris 151127128Snectar BUF_strlcat(buf,"DEK-Info: ",PEM_BUFSIZE); 152127128Snectar BUF_strlcat(buf,type,PEM_BUFSIZE); 153127128Snectar BUF_strlcat(buf,",",PEM_BUFSIZE); 15455714Skris j=strlen(buf); 155127128Snectar if (j + (len * 2) + 1 > PEM_BUFSIZE) 156127128Snectar return; 15755714Skris for (i=0; i<len; i++) 15855714Skris { 15955714Skris buf[j+i*2] =map[(str[i]>>4)&0x0f]; 16055714Skris buf[j+i*2+1]=map[(str[i] )&0x0f]; 16155714Skris } 16255714Skris buf[j+i*2]='\n'; 16355714Skris buf[j+i*2+1]='\0'; 16455714Skris } 16555714Skris 166109998Smarkm#ifndef OPENSSL_NO_FP_API 167160814Ssimonvoid *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x, 168160814Ssimon pem_password_cb *cb, void *u) 16955714Skris { 17055714Skris BIO *b; 171160814Ssimon void *ret; 17255714Skris 17355714Skris if ((b=BIO_new(BIO_s_file())) == NULL) 17455714Skris { 17555714Skris PEMerr(PEM_F_PEM_ASN1_READ,ERR_R_BUF_LIB); 17655714Skris return(0); 17755714Skris } 17855714Skris BIO_set_fp(b,fp,BIO_NOCLOSE); 17955714Skris ret=PEM_ASN1_read_bio(d2i,name,b,x,cb,u); 18055714Skris BIO_free(b); 18155714Skris return(ret); 18255714Skris } 18355714Skris#endif 18455714Skris 18559191Skrisstatic int check_pem(const char *nm, const char *name) 18659191Skris{ 18759191Skris /* Normal matching nm and name */ 18859191Skris if (!strcmp(nm,name)) return 1; 18959191Skris 19059191Skris /* Make PEM_STRING_EVP_PKEY match any private key */ 19159191Skris 192238405Sjkim if(!strcmp(name,PEM_STRING_EVP_PKEY)) 193238405Sjkim { 194238405Sjkim int slen; 195238405Sjkim const EVP_PKEY_ASN1_METHOD *ameth; 196238405Sjkim if(!strcmp(nm,PEM_STRING_PKCS8)) 197238405Sjkim return 1; 198238405Sjkim if(!strcmp(nm,PEM_STRING_PKCS8INF)) 199238405Sjkim return 1; 200238405Sjkim slen = pem_check_suffix(nm, "PRIVATE KEY"); 201238405Sjkim if (slen > 0) 202238405Sjkim { 203238405Sjkim /* NB: ENGINE implementations wont contain 204238405Sjkim * a deprecated old private key decode function 205238405Sjkim * so don't look for them. 206238405Sjkim */ 207238405Sjkim ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen); 208238405Sjkim if (ameth && ameth->old_priv_decode) 209238405Sjkim return 1; 210238405Sjkim } 211238405Sjkim return 0; 212238405Sjkim } 21359191Skris 214238405Sjkim if(!strcmp(name,PEM_STRING_PARAMETERS)) 215238405Sjkim { 216238405Sjkim int slen; 217238405Sjkim const EVP_PKEY_ASN1_METHOD *ameth; 218238405Sjkim slen = pem_check_suffix(nm, "PARAMETERS"); 219238405Sjkim if (slen > 0) 220238405Sjkim { 221238405Sjkim ENGINE *e; 222238405Sjkim ameth = EVP_PKEY_asn1_find_str(&e, nm, slen); 223238405Sjkim if (ameth) 224238405Sjkim { 225238405Sjkim int r; 226238405Sjkim if (ameth->param_decode) 227238405Sjkim r = 1; 228238405Sjkim else 229238405Sjkim r = 0; 230238405Sjkim#ifndef OPENSSL_NO_ENGINE 231238405Sjkim if (e) 232238405Sjkim ENGINE_finish(e); 233238405Sjkim#endif 234238405Sjkim return r; 235238405Sjkim } 236238405Sjkim } 237238405Sjkim return 0; 238238405Sjkim } 23959191Skris 24059191Skris /* Permit older strings */ 24159191Skris 24259191Skris if(!strcmp(nm,PEM_STRING_X509_OLD) && 24359191Skris !strcmp(name,PEM_STRING_X509)) return 1; 24459191Skris 24559191Skris if(!strcmp(nm,PEM_STRING_X509_REQ_OLD) && 24659191Skris !strcmp(name,PEM_STRING_X509_REQ)) return 1; 24759191Skris 24859191Skris /* Allow normal certs to be read as trusted certs */ 24959191Skris if(!strcmp(nm,PEM_STRING_X509) && 25059191Skris !strcmp(name,PEM_STRING_X509_TRUSTED)) return 1; 25159191Skris 25259191Skris if(!strcmp(nm,PEM_STRING_X509_OLD) && 25359191Skris !strcmp(name,PEM_STRING_X509_TRUSTED)) return 1; 25459191Skris 25559191Skris /* Some CAs use PKCS#7 with CERTIFICATE headers */ 25659191Skris if(!strcmp(nm, PEM_STRING_X509) && 25759191Skris !strcmp(name, PEM_STRING_PKCS7)) return 1; 25859191Skris 259194206Ssimon if(!strcmp(nm, PEM_STRING_PKCS7_SIGNED) && 260194206Ssimon !strcmp(name, PEM_STRING_PKCS7)) return 1; 261194206Ssimon 262238405Sjkim#ifndef OPENSSL_NO_CMS 263238405Sjkim if(!strcmp(nm, PEM_STRING_X509) && 264238405Sjkim !strcmp(name, PEM_STRING_CMS)) return 1; 265238405Sjkim /* Allow CMS to be read from PKCS#7 headers */ 266238405Sjkim if(!strcmp(nm, PEM_STRING_PKCS7) && 267238405Sjkim !strcmp(name, PEM_STRING_CMS)) return 1; 268238405Sjkim#endif 269238405Sjkim 27059191Skris return 0; 27159191Skris} 27259191Skris 273109998Smarkmint PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp, 27455714Skris pem_password_cb *cb, void *u) 27555714Skris { 27655714Skris EVP_CIPHER_INFO cipher; 27755714Skris char *nm=NULL,*header=NULL; 278109998Smarkm unsigned char *data=NULL; 27955714Skris long len; 280109998Smarkm int ret = 0; 28155714Skris 28255714Skris for (;;) 28355714Skris { 28459191Skris if (!PEM_read_bio(bp,&nm,&header,&data,&len)) { 28559191Skris if(ERR_GET_REASON(ERR_peek_error()) == 28659191Skris PEM_R_NO_START_LINE) 28759191Skris ERR_add_error_data(2, "Expecting: ", name); 288109998Smarkm return 0; 28959191Skris } 29059191Skris if(check_pem(nm, name)) break; 29168651Skris OPENSSL_free(nm); 29268651Skris OPENSSL_free(header); 29368651Skris OPENSSL_free(data); 29455714Skris } 29555714Skris if (!PEM_get_EVP_CIPHER_INFO(header,&cipher)) goto err; 29655714Skris if (!PEM_do_header(&cipher,data,&len,cb,u)) goto err; 297109998Smarkm 298109998Smarkm *pdata = data; 299109998Smarkm *plen = len; 300109998Smarkm 301109998Smarkm if (pnm) 302109998Smarkm *pnm = nm; 303109998Smarkm 304109998Smarkm ret = 1; 305109998Smarkm 30655714Skriserr: 307109998Smarkm if (!ret || !pnm) OPENSSL_free(nm); 30868651Skris OPENSSL_free(header); 309109998Smarkm if (!ret) OPENSSL_free(data); 310109998Smarkm return ret; 31155714Skris } 31255714Skris 313109998Smarkm#ifndef OPENSSL_NO_FP_API 314160814Ssimonint PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, 315238405Sjkim void *x, const EVP_CIPHER *enc, unsigned char *kstr, 316160814Ssimon int klen, pem_password_cb *callback, void *u) 31755714Skris { 31855714Skris BIO *b; 31955714Skris int ret; 32055714Skris 32155714Skris if ((b=BIO_new(BIO_s_file())) == NULL) 32255714Skris { 32355714Skris PEMerr(PEM_F_PEM_ASN1_WRITE,ERR_R_BUF_LIB); 32455714Skris return(0); 32555714Skris } 32655714Skris BIO_set_fp(b,fp,BIO_NOCLOSE); 32755714Skris ret=PEM_ASN1_write_bio(i2d,name,b,x,enc,kstr,klen,callback,u); 32855714Skris BIO_free(b); 32955714Skris return(ret); 33055714Skris } 33155714Skris#endif 33255714Skris 333160814Ssimonint PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, 334238405Sjkim void *x, const EVP_CIPHER *enc, unsigned char *kstr, 335160814Ssimon int klen, pem_password_cb *callback, void *u) 33655714Skris { 33755714Skris EVP_CIPHER_CTX ctx; 33855714Skris int dsize=0,i,j,ret=0; 33955714Skris unsigned char *p,*data=NULL; 34055714Skris const char *objstr=NULL; 34155714Skris char buf[PEM_BUFSIZE]; 34255714Skris unsigned char key[EVP_MAX_KEY_LENGTH]; 34355714Skris unsigned char iv[EVP_MAX_IV_LENGTH]; 34455714Skris 34555714Skris if (enc != NULL) 34655714Skris { 34755714Skris objstr=OBJ_nid2sn(EVP_CIPHER_nid(enc)); 34855714Skris if (objstr == NULL) 34955714Skris { 35055714Skris PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_UNSUPPORTED_CIPHER); 35155714Skris goto err; 35255714Skris } 35355714Skris } 35455714Skris 35555714Skris if ((dsize=i2d(x,NULL)) < 0) 35655714Skris { 357160814Ssimon PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_ASN1_LIB); 35855714Skris dsize=0; 35955714Skris goto err; 36055714Skris } 36155714Skris /* dzise + 8 bytes are needed */ 362109998Smarkm /* actually it needs the cipher block size extra... */ 36368651Skris data=(unsigned char *)OPENSSL_malloc((unsigned int)dsize+20); 36455714Skris if (data == NULL) 36555714Skris { 36655714Skris PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_MALLOC_FAILURE); 36755714Skris goto err; 36855714Skris } 36955714Skris p=data; 37055714Skris i=i2d(x,&p); 37155714Skris 37255714Skris if (enc != NULL) 37355714Skris { 37455714Skris if (kstr == NULL) 37555714Skris { 37655714Skris if (callback == NULL) 377109998Smarkm klen=PEM_def_callback(buf,PEM_BUFSIZE,1,u); 37855714Skris else 37955714Skris klen=(*callback)(buf,PEM_BUFSIZE,1,u); 38055714Skris if (klen <= 0) 38155714Skris { 38255714Skris PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_READ_KEY); 38355714Skris goto err; 38455714Skris } 38555714Skris#ifdef CHARSET_EBCDIC 38655714Skris /* Convert the pass phrase from EBCDIC */ 38755714Skris ebcdic2ascii(buf, buf, klen); 38855714Skris#endif 38955714Skris kstr=(unsigned char *)buf; 39055714Skris } 39159191Skris RAND_add(data,i,0);/* put in the RSA key. */ 392160814Ssimon OPENSSL_assert(enc->iv_len <= (int)sizeof(iv)); 393100928Snectar if (RAND_pseudo_bytes(iv,enc->iv_len) < 0) /* Generate a salt */ 39459191Skris goto err; 39555714Skris /* The 'iv' is used as the iv and as a salt. It is 39655714Skris * NOT taken from the BytesToKey function */ 397246772Sjkim if (!EVP_BytesToKey(enc,EVP_md5(),iv,kstr,klen,1,key,NULL)) 398246772Sjkim goto err; 39955714Skris 400109998Smarkm if (kstr == (unsigned char *)buf) OPENSSL_cleanse(buf,PEM_BUFSIZE); 40155714Skris 402109998Smarkm OPENSSL_assert(strlen(objstr)+23+2*enc->iv_len+13 <= sizeof buf); 403109998Smarkm 40455714Skris buf[0]='\0'; 40555714Skris PEM_proc_type(buf,PEM_TYPE_ENCRYPTED); 406100928Snectar PEM_dek_info(buf,objstr,enc->iv_len,(char *)iv); 40755714Skris /* k=strlen(buf); */ 408109998Smarkm 409109998Smarkm EVP_CIPHER_CTX_init(&ctx); 410246772Sjkim ret = 1; 411246772Sjkim if (!EVP_EncryptInit_ex(&ctx,enc,NULL,key,iv) 412246772Sjkim || !EVP_EncryptUpdate(&ctx,data,&j,data,i) 413246772Sjkim || !EVP_EncryptFinal_ex(&ctx,&(data[j]),&i)) 414246772Sjkim ret = 0; 415109998Smarkm EVP_CIPHER_CTX_cleanup(&ctx); 416246772Sjkim if (ret == 0) 417246772Sjkim goto err; 41855714Skris i+=j; 41955714Skris } 42055714Skris else 42155714Skris { 42255714Skris ret=1; 42355714Skris buf[0]='\0'; 42455714Skris } 42555714Skris i=PEM_write_bio(bp,name,buf,data,i); 42655714Skris if (i <= 0) ret=0; 42755714Skriserr: 428109998Smarkm OPENSSL_cleanse(key,sizeof(key)); 429109998Smarkm OPENSSL_cleanse(iv,sizeof(iv)); 430109998Smarkm OPENSSL_cleanse((char *)&ctx,sizeof(ctx)); 431109998Smarkm OPENSSL_cleanse(buf,PEM_BUFSIZE); 432109998Smarkm if (data != NULL) 433109998Smarkm { 434109998Smarkm OPENSSL_cleanse(data,(unsigned int)dsize); 435109998Smarkm OPENSSL_free(data); 436109998Smarkm } 43755714Skris return(ret); 43855714Skris } 43955714Skris 44055714Skrisint PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen, 44155714Skris pem_password_cb *callback,void *u) 44255714Skris { 44355714Skris int i,j,o,klen; 44455714Skris long len; 44555714Skris EVP_CIPHER_CTX ctx; 44655714Skris unsigned char key[EVP_MAX_KEY_LENGTH]; 44755714Skris char buf[PEM_BUFSIZE]; 44855714Skris 44955714Skris len= *plen; 45055714Skris 45155714Skris if (cipher->cipher == NULL) return(1); 45255714Skris if (callback == NULL) 453109998Smarkm klen=PEM_def_callback(buf,PEM_BUFSIZE,0,u); 45455714Skris else 45555714Skris klen=callback(buf,PEM_BUFSIZE,0,u); 45655714Skris if (klen <= 0) 45755714Skris { 45855714Skris PEMerr(PEM_F_PEM_DO_HEADER,PEM_R_BAD_PASSWORD_READ); 45955714Skris return(0); 46055714Skris } 46155714Skris#ifdef CHARSET_EBCDIC 46255714Skris /* Convert the pass phrase from EBCDIC */ 46355714Skris ebcdic2ascii(buf, buf, klen); 46455714Skris#endif 46555714Skris 466246772Sjkim if (!EVP_BytesToKey(cipher->cipher,EVP_md5(),&(cipher->iv[0]), 467246772Sjkim (unsigned char *)buf,klen,1,key,NULL)) 468246772Sjkim return 0; 46955714Skris 47055714Skris j=(int)len; 471109998Smarkm EVP_CIPHER_CTX_init(&ctx); 472246772Sjkim o = EVP_DecryptInit_ex(&ctx,cipher->cipher,NULL, key,&(cipher->iv[0])); 473246772Sjkim if (o) 474246772Sjkim o = EVP_DecryptUpdate(&ctx,data,&i,data,j); 475246772Sjkim if (o) 476246772Sjkim o = EVP_DecryptFinal_ex(&ctx,&(data[i]),&j); 47755714Skris EVP_CIPHER_CTX_cleanup(&ctx); 478109998Smarkm OPENSSL_cleanse((char *)buf,sizeof(buf)); 479109998Smarkm OPENSSL_cleanse((char *)key,sizeof(key)); 48055714Skris j+=i; 48155714Skris if (!o) 48255714Skris { 48355714Skris PEMerr(PEM_F_PEM_DO_HEADER,PEM_R_BAD_DECRYPT); 48455714Skris return(0); 48555714Skris } 48655714Skris *plen=j; 48755714Skris return(1); 48855714Skris } 48955714Skris 49055714Skrisint PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) 49155714Skris { 49255714Skris const EVP_CIPHER *enc=NULL; 49355714Skris char *p,c; 494160814Ssimon char **header_pp = &header; 49555714Skris 49655714Skris cipher->cipher=NULL; 49755714Skris if ((header == NULL) || (*header == '\0') || (*header == '\n')) 49855714Skris return(1); 49955714Skris if (strncmp(header,"Proc-Type: ",11) != 0) 50055714Skris { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_PROC_TYPE); return(0); } 50155714Skris header+=11; 50255714Skris if (*header != '4') return(0); header++; 50355714Skris if (*header != ',') return(0); header++; 50455714Skris if (strncmp(header,"ENCRYPTED",9) != 0) 50555714Skris { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_ENCRYPTED); return(0); } 50655714Skris for (; (*header != '\n') && (*header != '\0'); header++) 50755714Skris ; 50855714Skris if (*header == '\0') 50955714Skris { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_SHORT_HEADER); return(0); } 51055714Skris header++; 51155714Skris if (strncmp(header,"DEK-Info: ",10) != 0) 51255714Skris { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_DEK_INFO); return(0); } 51355714Skris header+=10; 51455714Skris 51555714Skris p=header; 51655714Skris for (;;) 51755714Skris { 51855714Skris c= *header; 51955714Skris#ifndef CHARSET_EBCDIC 52055714Skris if (!( ((c >= 'A') && (c <= 'Z')) || (c == '-') || 52155714Skris ((c >= '0') && (c <= '9')))) 52255714Skris break; 52355714Skris#else 52455714Skris if (!( isupper(c) || (c == '-') || 52555714Skris isdigit(c))) 52655714Skris break; 52755714Skris#endif 52855714Skris header++; 52955714Skris } 53055714Skris *header='\0'; 53155714Skris cipher->cipher=enc=EVP_get_cipherbyname(p); 53255714Skris *header=c; 53355714Skris header++; 53455714Skris 53555714Skris if (enc == NULL) 53655714Skris { 53755714Skris PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_UNSUPPORTED_ENCRYPTION); 53855714Skris return(0); 53955714Skris } 540160814Ssimon if (!load_iv(header_pp,&(cipher->iv[0]),enc->iv_len)) 541160814Ssimon return(0); 54255714Skris 54355714Skris return(1); 54455714Skris } 54555714Skris 546160814Ssimonstatic int load_iv(char **fromp, unsigned char *to, int num) 54755714Skris { 54855714Skris int v,i; 549160814Ssimon char *from; 55055714Skris 55155714Skris from= *fromp; 55255714Skris for (i=0; i<num; i++) to[i]=0; 55355714Skris num*=2; 55455714Skris for (i=0; i<num; i++) 55555714Skris { 55655714Skris if ((*from >= '0') && (*from <= '9')) 55755714Skris v= *from-'0'; 55855714Skris else if ((*from >= 'A') && (*from <= 'F')) 55955714Skris v= *from-'A'+10; 56055714Skris else if ((*from >= 'a') && (*from <= 'f')) 56155714Skris v= *from-'a'+10; 56255714Skris else 56355714Skris { 56455714Skris PEMerr(PEM_F_LOAD_IV,PEM_R_BAD_IV_CHARS); 56555714Skris return(0); 56655714Skris } 56755714Skris from++; 56855714Skris to[i/2]|=v<<(long)((!(i&1))*4); 56955714Skris } 57055714Skris 57155714Skris *fromp=from; 57255714Skris return(1); 57355714Skris } 57455714Skris 575109998Smarkm#ifndef OPENSSL_NO_FP_API 57655714Skrisint PEM_write(FILE *fp, char *name, char *header, unsigned char *data, 57755714Skris long len) 57855714Skris { 57955714Skris BIO *b; 58055714Skris int ret; 58155714Skris 58255714Skris if ((b=BIO_new(BIO_s_file())) == NULL) 58355714Skris { 58455714Skris PEMerr(PEM_F_PEM_WRITE,ERR_R_BUF_LIB); 58555714Skris return(0); 58655714Skris } 58755714Skris BIO_set_fp(b,fp,BIO_NOCLOSE); 58855714Skris ret=PEM_write_bio(b, name, header, data,len); 58955714Skris BIO_free(b); 59055714Skris return(ret); 59155714Skris } 59255714Skris#endif 59355714Skris 59455714Skrisint PEM_write_bio(BIO *bp, const char *name, char *header, unsigned char *data, 59555714Skris long len) 59655714Skris { 59755714Skris int nlen,n,i,j,outl; 598127128Snectar unsigned char *buf = NULL; 59955714Skris EVP_ENCODE_CTX ctx; 60055714Skris int reason=ERR_R_BUF_LIB; 60155714Skris 60255714Skris EVP_EncodeInit(&ctx); 60355714Skris nlen=strlen(name); 60455714Skris 60555714Skris if ( (BIO_write(bp,"-----BEGIN ",11) != 11) || 60655714Skris (BIO_write(bp,name,nlen) != nlen) || 60755714Skris (BIO_write(bp,"-----\n",6) != 6)) 60855714Skris goto err; 60955714Skris 61055714Skris i=strlen(header); 61155714Skris if (i > 0) 61255714Skris { 61355714Skris if ( (BIO_write(bp,header,i) != i) || 61455714Skris (BIO_write(bp,"\n",1) != 1)) 61555714Skris goto err; 61655714Skris } 61755714Skris 618127128Snectar buf = OPENSSL_malloc(PEM_BUFSIZE*8); 61955714Skris if (buf == NULL) 62055714Skris { 62155714Skris reason=ERR_R_MALLOC_FAILURE; 62255714Skris goto err; 62355714Skris } 62455714Skris 62555714Skris i=j=0; 62655714Skris while (len > 0) 62755714Skris { 62855714Skris n=(int)((len>(PEM_BUFSIZE*5))?(PEM_BUFSIZE*5):len); 62955714Skris EVP_EncodeUpdate(&ctx,buf,&outl,&(data[j]),n); 63055714Skris if ((outl) && (BIO_write(bp,(char *)buf,outl) != outl)) 63155714Skris goto err; 63255714Skris i+=outl; 63355714Skris len-=n; 63455714Skris j+=n; 63555714Skris } 63655714Skris EVP_EncodeFinal(&ctx,buf,&outl); 63755714Skris if ((outl > 0) && (BIO_write(bp,(char *)buf,outl) != outl)) goto err; 638167612Ssimon OPENSSL_cleanse(buf, PEM_BUFSIZE*8); 63968651Skris OPENSSL_free(buf); 640127128Snectar buf = NULL; 64155714Skris if ( (BIO_write(bp,"-----END ",9) != 9) || 64255714Skris (BIO_write(bp,name,nlen) != nlen) || 64355714Skris (BIO_write(bp,"-----\n",6) != 6)) 64455714Skris goto err; 64555714Skris return(i+outl); 64655714Skriserr: 647167612Ssimon if (buf) { 648167612Ssimon OPENSSL_cleanse(buf, PEM_BUFSIZE*8); 649127128Snectar OPENSSL_free(buf); 650167612Ssimon } 65155714Skris PEMerr(PEM_F_PEM_WRITE_BIO,reason); 65255714Skris return(0); 65355714Skris } 65455714Skris 655109998Smarkm#ifndef OPENSSL_NO_FP_API 65655714Skrisint PEM_read(FILE *fp, char **name, char **header, unsigned char **data, 65755714Skris long *len) 65855714Skris { 65955714Skris BIO *b; 66055714Skris int ret; 66155714Skris 66255714Skris if ((b=BIO_new(BIO_s_file())) == NULL) 66355714Skris { 66455714Skris PEMerr(PEM_F_PEM_READ,ERR_R_BUF_LIB); 66555714Skris return(0); 66655714Skris } 66755714Skris BIO_set_fp(b,fp,BIO_NOCLOSE); 66855714Skris ret=PEM_read_bio(b, name, header, data,len); 66955714Skris BIO_free(b); 67055714Skris return(ret); 67155714Skris } 67255714Skris#endif 67355714Skris 67455714Skrisint PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data, 67555714Skris long *len) 67655714Skris { 67755714Skris EVP_ENCODE_CTX ctx; 67855714Skris int end=0,i,k,bl=0,hl=0,nohead=0; 67955714Skris char buf[256]; 68055714Skris BUF_MEM *nameB; 68155714Skris BUF_MEM *headerB; 68255714Skris BUF_MEM *dataB,*tmpB; 68355714Skris 68455714Skris nameB=BUF_MEM_new(); 68555714Skris headerB=BUF_MEM_new(); 68655714Skris dataB=BUF_MEM_new(); 68755714Skris if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL)) 68855714Skris { 689160814Ssimon BUF_MEM_free(nameB); 690160814Ssimon BUF_MEM_free(headerB); 691160814Ssimon BUF_MEM_free(dataB); 69255714Skris PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); 69355714Skris return(0); 69455714Skris } 69555714Skris 69655714Skris buf[254]='\0'; 69755714Skris for (;;) 69855714Skris { 69955714Skris i=BIO_gets(bp,buf,254); 70055714Skris 70155714Skris if (i <= 0) 70255714Skris { 70355714Skris PEMerr(PEM_F_PEM_READ_BIO,PEM_R_NO_START_LINE); 70455714Skris goto err; 70555714Skris } 70655714Skris 70755714Skris while ((i >= 0) && (buf[i] <= ' ')) i--; 70855714Skris buf[++i]='\n'; buf[++i]='\0'; 70955714Skris 71055714Skris if (strncmp(buf,"-----BEGIN ",11) == 0) 71155714Skris { 71255714Skris i=strlen(&(buf[11])); 71355714Skris 71455714Skris if (strncmp(&(buf[11+i-6]),"-----\n",6) != 0) 71555714Skris continue; 71655714Skris if (!BUF_MEM_grow(nameB,i+9)) 71755714Skris { 71855714Skris PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); 71955714Skris goto err; 72055714Skris } 72155714Skris memcpy(nameB->data,&(buf[11]),i-6); 72255714Skris nameB->data[i-6]='\0'; 72355714Skris break; 72455714Skris } 72555714Skris } 72655714Skris hl=0; 72755714Skris if (!BUF_MEM_grow(headerB,256)) 72855714Skris { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; } 72955714Skris headerB->data[0]='\0'; 73055714Skris for (;;) 73155714Skris { 73255714Skris i=BIO_gets(bp,buf,254); 73355714Skris if (i <= 0) break; 73455714Skris 73555714Skris while ((i >= 0) && (buf[i] <= ' ')) i--; 73655714Skris buf[++i]='\n'; buf[++i]='\0'; 73755714Skris 73855714Skris if (buf[0] == '\n') break; 73955714Skris if (!BUF_MEM_grow(headerB,hl+i+9)) 74055714Skris { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; } 74155714Skris if (strncmp(buf,"-----END ",9) == 0) 74255714Skris { 74355714Skris nohead=1; 74455714Skris break; 74555714Skris } 74655714Skris memcpy(&(headerB->data[hl]),buf,i); 74755714Skris headerB->data[hl+i]='\0'; 74855714Skris hl+=i; 74955714Skris } 75055714Skris 75155714Skris bl=0; 75255714Skris if (!BUF_MEM_grow(dataB,1024)) 75355714Skris { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; } 75455714Skris dataB->data[0]='\0'; 75555714Skris if (!nohead) 75655714Skris { 75755714Skris for (;;) 75855714Skris { 75955714Skris i=BIO_gets(bp,buf,254); 76055714Skris if (i <= 0) break; 76155714Skris 76255714Skris while ((i >= 0) && (buf[i] <= ' ')) i--; 76355714Skris buf[++i]='\n'; buf[++i]='\0'; 76455714Skris 76555714Skris if (i != 65) end=1; 76655714Skris if (strncmp(buf,"-----END ",9) == 0) 76755714Skris break; 76855714Skris if (i > 65) break; 769109998Smarkm if (!BUF_MEM_grow_clean(dataB,i+bl+9)) 77055714Skris { 77155714Skris PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); 77255714Skris goto err; 77355714Skris } 77455714Skris memcpy(&(dataB->data[bl]),buf,i); 77555714Skris dataB->data[bl+i]='\0'; 77655714Skris bl+=i; 77755714Skris if (end) 77855714Skris { 77955714Skris buf[0]='\0'; 78055714Skris i=BIO_gets(bp,buf,254); 78155714Skris if (i <= 0) break; 78255714Skris 78355714Skris while ((i >= 0) && (buf[i] <= ' ')) i--; 78455714Skris buf[++i]='\n'; buf[++i]='\0'; 78555714Skris 78655714Skris break; 78755714Skris } 78855714Skris } 78955714Skris } 79055714Skris else 79155714Skris { 79255714Skris tmpB=headerB; 79355714Skris headerB=dataB; 79455714Skris dataB=tmpB; 79555714Skris bl=hl; 79655714Skris } 79755714Skris i=strlen(nameB->data); 79855714Skris if ( (strncmp(buf,"-----END ",9) != 0) || 79955714Skris (strncmp(nameB->data,&(buf[9]),i) != 0) || 80055714Skris (strncmp(&(buf[9+i]),"-----\n",6) != 0)) 80155714Skris { 80255714Skris PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_END_LINE); 80355714Skris goto err; 80455714Skris } 80555714Skris 80655714Skris EVP_DecodeInit(&ctx); 80755714Skris i=EVP_DecodeUpdate(&ctx, 80855714Skris (unsigned char *)dataB->data,&bl, 80955714Skris (unsigned char *)dataB->data,bl); 81055714Skris if (i < 0) 81155714Skris { 81255714Skris PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE); 81355714Skris goto err; 81455714Skris } 81555714Skris i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k); 81655714Skris if (i < 0) 81755714Skris { 81855714Skris PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE); 81955714Skris goto err; 82055714Skris } 82155714Skris bl+=k; 82255714Skris 82355714Skris if (bl == 0) goto err; 82455714Skris *name=nameB->data; 82555714Skris *header=headerB->data; 82655714Skris *data=(unsigned char *)dataB->data; 82755714Skris *len=bl; 82868651Skris OPENSSL_free(nameB); 82968651Skris OPENSSL_free(headerB); 83068651Skris OPENSSL_free(dataB); 83155714Skris return(1); 83255714Skriserr: 83355714Skris BUF_MEM_free(nameB); 83455714Skris BUF_MEM_free(headerB); 83555714Skris BUF_MEM_free(dataB); 83655714Skris return(0); 83755714Skris } 838238405Sjkim 839238405Sjkim/* Check pem string and return prefix length. 840238405Sjkim * If for example the pem_str == "RSA PRIVATE KEY" and suffix = "PRIVATE KEY" 841238405Sjkim * the return value is 3 for the string "RSA". 842238405Sjkim */ 843238405Sjkim 844238405Sjkimint pem_check_suffix(const char *pem_str, const char *suffix) 845238405Sjkim { 846238405Sjkim int pem_len = strlen(pem_str); 847238405Sjkim int suffix_len = strlen(suffix); 848238405Sjkim const char *p; 849238405Sjkim if (suffix_len + 1 >= pem_len) 850238405Sjkim return 0; 851238405Sjkim p = pem_str + pem_len - suffix_len; 852238405Sjkim if (strcmp(p, suffix)) 853238405Sjkim return 0; 854238405Sjkim p--; 855238405Sjkim if (*p != ' ') 856238405Sjkim return 0; 857238405Sjkim return p - pem_str; 858238405Sjkim } 859238405Sjkim 860