155714Skris/* crypto/pem/pem_info.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. 8280304Sjkim * 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). 15280304Sjkim * 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. 22280304Sjkim * 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 :-). 37280304Sjkim * 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)" 40280304Sjkim * 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. 52280304Sjkim * 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> 6055714Skris#include "cryptlib.h" 6155714Skris#include <openssl/buffer.h> 6255714Skris#include <openssl/objects.h> 6355714Skris#include <openssl/evp.h> 6455714Skris#include <openssl/x509.h> 6555714Skris#include <openssl/pem.h> 66160814Ssimon#ifndef OPENSSL_NO_RSA 67280304Sjkim# include <openssl/rsa.h> 68160814Ssimon#endif 69160814Ssimon#ifndef OPENSSL_NO_DSA 70280304Sjkim# include <openssl/dsa.h> 71160814Ssimon#endif 7255714Skris 73109998Smarkm#ifndef OPENSSL_NO_FP_API 74280304SjkimSTACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, 75280304Sjkim pem_password_cb *cb, void *u) 76280304Sjkim{ 77280304Sjkim BIO *b; 78280304Sjkim STACK_OF(X509_INFO) *ret; 7955714Skris 80280304Sjkim if ((b = BIO_new(BIO_s_file())) == NULL) { 81280304Sjkim PEMerr(PEM_F_PEM_X509_INFO_READ, ERR_R_BUF_LIB); 82280304Sjkim return (0); 83280304Sjkim } 84280304Sjkim BIO_set_fp(b, fp, BIO_NOCLOSE); 85280304Sjkim ret = PEM_X509_INFO_read_bio(b, sk, cb, u); 86280304Sjkim BIO_free(b); 87280304Sjkim return (ret); 88280304Sjkim} 8955714Skris#endif 9055714Skris 91280304SjkimSTACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, 92280304Sjkim pem_password_cb *cb, void *u) 93280304Sjkim{ 94280304Sjkim X509_INFO *xi = NULL; 95280304Sjkim char *name = NULL, *header = NULL; 96280304Sjkim void *pp; 97280304Sjkim unsigned char *data = NULL; 98280304Sjkim const unsigned char *p; 99280304Sjkim long len, error = 0; 100280304Sjkim int ok = 0; 101280304Sjkim STACK_OF(X509_INFO) *ret = NULL; 102280304Sjkim unsigned int i, raw, ptype; 103280304Sjkim d2i_of_void *d2i = 0; 10455714Skris 105280304Sjkim if (sk == NULL) { 106280304Sjkim if ((ret = sk_X509_INFO_new_null()) == NULL) { 107280304Sjkim PEMerr(PEM_F_PEM_X509_INFO_READ_BIO, ERR_R_MALLOC_FAILURE); 108280304Sjkim goto err; 109280304Sjkim } 110280304Sjkim } else 111280304Sjkim ret = sk; 11255714Skris 113280304Sjkim if ((xi = X509_INFO_new()) == NULL) 114280304Sjkim goto err; 115280304Sjkim for (;;) { 116280304Sjkim raw = 0; 117280304Sjkim ptype = 0; 118280304Sjkim i = PEM_read_bio(bp, &name, &header, &data, &len); 119280304Sjkim if (i == 0) { 120280304Sjkim error = ERR_GET_REASON(ERR_peek_last_error()); 121280304Sjkim if (error == PEM_R_NO_START_LINE) { 122280304Sjkim ERR_clear_error(); 123280304Sjkim break; 124280304Sjkim } 125280304Sjkim goto err; 126280304Sjkim } 127280304Sjkim start: 128280304Sjkim if ((strcmp(name, PEM_STRING_X509) == 0) || 129280304Sjkim (strcmp(name, PEM_STRING_X509_OLD) == 0)) { 130280304Sjkim d2i = (D2I_OF(void)) d2i_X509; 131280304Sjkim if (xi->x509 != NULL) { 132280304Sjkim if (!sk_X509_INFO_push(ret, xi)) 133280304Sjkim goto err; 134280304Sjkim if ((xi = X509_INFO_new()) == NULL) 135280304Sjkim goto err; 136280304Sjkim goto start; 137280304Sjkim } 138280304Sjkim pp = &(xi->x509); 139280304Sjkim } else if ((strcmp(name, PEM_STRING_X509_TRUSTED) == 0)) { 140280304Sjkim d2i = (D2I_OF(void)) d2i_X509_AUX; 141280304Sjkim if (xi->x509 != NULL) { 142280304Sjkim if (!sk_X509_INFO_push(ret, xi)) 143280304Sjkim goto err; 144280304Sjkim if ((xi = X509_INFO_new()) == NULL) 145280304Sjkim goto err; 146280304Sjkim goto start; 147280304Sjkim } 148280304Sjkim pp = &(xi->x509); 149280304Sjkim } else if (strcmp(name, PEM_STRING_X509_CRL) == 0) { 150280304Sjkim d2i = (D2I_OF(void)) d2i_X509_CRL; 151280304Sjkim if (xi->crl != NULL) { 152280304Sjkim if (!sk_X509_INFO_push(ret, xi)) 153280304Sjkim goto err; 154280304Sjkim if ((xi = X509_INFO_new()) == NULL) 155280304Sjkim goto err; 156280304Sjkim goto start; 157280304Sjkim } 158280304Sjkim pp = &(xi->crl); 159280304Sjkim } else 160109998Smarkm#ifndef OPENSSL_NO_RSA 161280304Sjkim if (strcmp(name, PEM_STRING_RSA) == 0) { 162280304Sjkim d2i = (D2I_OF(void)) d2i_RSAPrivateKey; 163280304Sjkim if (xi->x_pkey != NULL) { 164280304Sjkim if (!sk_X509_INFO_push(ret, xi)) 165280304Sjkim goto err; 166280304Sjkim if ((xi = X509_INFO_new()) == NULL) 167280304Sjkim goto err; 168280304Sjkim goto start; 169280304Sjkim } 17055714Skris 171280304Sjkim xi->enc_data = NULL; 172280304Sjkim xi->enc_len = 0; 17355714Skris 174280304Sjkim xi->x_pkey = X509_PKEY_new(); 175291721Sjkim if (xi->x_pkey == NULL) 176291721Sjkim goto err; 177280304Sjkim ptype = EVP_PKEY_RSA; 178280304Sjkim pp = &xi->x_pkey->dec_pkey; 179280304Sjkim if ((int)strlen(header) > 10) /* assume encrypted */ 180280304Sjkim raw = 1; 181280304Sjkim } else 18255714Skris#endif 183109998Smarkm#ifndef OPENSSL_NO_DSA 184280304Sjkim if (strcmp(name, PEM_STRING_DSA) == 0) { 185280304Sjkim d2i = (D2I_OF(void)) d2i_DSAPrivateKey; 186280304Sjkim if (xi->x_pkey != NULL) { 187280304Sjkim if (!sk_X509_INFO_push(ret, xi)) 188280304Sjkim goto err; 189280304Sjkim if ((xi = X509_INFO_new()) == NULL) 190280304Sjkim goto err; 191280304Sjkim goto start; 192280304Sjkim } 19355714Skris 194280304Sjkim xi->enc_data = NULL; 195280304Sjkim xi->enc_len = 0; 19655714Skris 197280304Sjkim xi->x_pkey = X509_PKEY_new(); 198291721Sjkim if (xi->x_pkey == NULL) 199291721Sjkim goto err; 200280304Sjkim ptype = EVP_PKEY_DSA; 201280304Sjkim pp = &xi->x_pkey->dec_pkey; 202280304Sjkim if ((int)strlen(header) > 10) /* assume encrypted */ 203280304Sjkim raw = 1; 204280304Sjkim } else 20555714Skris#endif 206160814Ssimon#ifndef OPENSSL_NO_EC 207280304Sjkim if (strcmp(name, PEM_STRING_ECPRIVATEKEY) == 0) { 208280304Sjkim d2i = (D2I_OF(void)) d2i_ECPrivateKey; 209280304Sjkim if (xi->x_pkey != NULL) { 210280304Sjkim if (!sk_X509_INFO_push(ret, xi)) 211280304Sjkim goto err; 212280304Sjkim if ((xi = X509_INFO_new()) == NULL) 213280304Sjkim goto err; 214280304Sjkim goto start; 215280304Sjkim } 216280304Sjkim 217280304Sjkim xi->enc_data = NULL; 218280304Sjkim xi->enc_len = 0; 219280304Sjkim 220280304Sjkim xi->x_pkey = X509_PKEY_new(); 221291721Sjkim if (xi->x_pkey == NULL) 222291721Sjkim goto err; 223280304Sjkim ptype = EVP_PKEY_EC; 224280304Sjkim pp = &xi->x_pkey->dec_pkey; 225280304Sjkim if ((int)strlen(header) > 10) /* assume encrypted */ 226280304Sjkim raw = 1; 227280304Sjkim } else 228160814Ssimon#endif 229280304Sjkim { 230280304Sjkim d2i = NULL; 231280304Sjkim pp = NULL; 232280304Sjkim } 23355714Skris 234280304Sjkim if (d2i != NULL) { 235280304Sjkim if (!raw) { 236280304Sjkim EVP_CIPHER_INFO cipher; 23755714Skris 238280304Sjkim if (!PEM_get_EVP_CIPHER_INFO(header, &cipher)) 239280304Sjkim goto err; 240280304Sjkim if (!PEM_do_header(&cipher, data, &len, cb, u)) 241280304Sjkim goto err; 242280304Sjkim p = data; 243280304Sjkim if (ptype) { 244280304Sjkim if (!d2i_PrivateKey(ptype, pp, &p, len)) { 245280304Sjkim PEMerr(PEM_F_PEM_X509_INFO_READ_BIO, ERR_R_ASN1_LIB); 246280304Sjkim goto err; 247280304Sjkim } 248280304Sjkim } else if (d2i(pp, &p, len) == NULL) { 249280304Sjkim PEMerr(PEM_F_PEM_X509_INFO_READ_BIO, ERR_R_ASN1_LIB); 250280304Sjkim goto err; 251280304Sjkim } 252280304Sjkim } else { /* encrypted RSA data */ 253280304Sjkim if (!PEM_get_EVP_CIPHER_INFO(header, &xi->enc_cipher)) 254280304Sjkim goto err; 255280304Sjkim xi->enc_data = (char *)data; 256280304Sjkim xi->enc_len = (int)len; 257280304Sjkim data = NULL; 258280304Sjkim } 259280304Sjkim } else { 260280304Sjkim /* unknown */ 261280304Sjkim } 262280304Sjkim if (name != NULL) 263280304Sjkim OPENSSL_free(name); 264280304Sjkim if (header != NULL) 265280304Sjkim OPENSSL_free(header); 266280304Sjkim if (data != NULL) 267280304Sjkim OPENSSL_free(data); 268280304Sjkim name = NULL; 269280304Sjkim header = NULL; 270280304Sjkim data = NULL; 271280304Sjkim } 27255714Skris 273280304Sjkim /* 274280304Sjkim * if the last one hasn't been pushed yet and there is anything in it 275280304Sjkim * then add it to the stack ... 276280304Sjkim */ 277280304Sjkim if ((xi->x509 != NULL) || (xi->crl != NULL) || 278280304Sjkim (xi->x_pkey != NULL) || (xi->enc_data != NULL)) { 279280304Sjkim if (!sk_X509_INFO_push(ret, xi)) 280280304Sjkim goto err; 281280304Sjkim xi = NULL; 282280304Sjkim } 283280304Sjkim ok = 1; 284280304Sjkim err: 285280304Sjkim if (xi != NULL) 286280304Sjkim X509_INFO_free(xi); 287280304Sjkim if (!ok) { 288280304Sjkim for (i = 0; ((int)i) < sk_X509_INFO_num(ret); i++) { 289280304Sjkim xi = sk_X509_INFO_value(ret, i); 290280304Sjkim X509_INFO_free(xi); 291280304Sjkim } 292280304Sjkim if (ret != sk) 293280304Sjkim sk_X509_INFO_free(ret); 294280304Sjkim ret = NULL; 295280304Sjkim } 29655714Skris 297280304Sjkim if (name != NULL) 298280304Sjkim OPENSSL_free(name); 299280304Sjkim if (header != NULL) 300280304Sjkim OPENSSL_free(header); 301280304Sjkim if (data != NULL) 302280304Sjkim OPENSSL_free(data); 303280304Sjkim return (ret); 304280304Sjkim} 30555714Skris 30655714Skris/* A TJH addition */ 30755714Skrisint PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc, 308280304Sjkim unsigned char *kstr, int klen, 309280304Sjkim pem_password_cb *cb, void *u) 310280304Sjkim{ 311280304Sjkim EVP_CIPHER_CTX ctx; 312280304Sjkim int i, ret = 0; 313280304Sjkim unsigned char *data = NULL; 314280304Sjkim const char *objstr = NULL; 315280304Sjkim char buf[PEM_BUFSIZE]; 316280304Sjkim unsigned char *iv = NULL; 31755714Skris 318280304Sjkim if (enc != NULL) { 319280304Sjkim objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc)); 320280304Sjkim if (objstr == NULL) { 321280304Sjkim PEMerr(PEM_F_PEM_X509_INFO_WRITE_BIO, PEM_R_UNSUPPORTED_CIPHER); 322280304Sjkim goto err; 323280304Sjkim } 324280304Sjkim } 325238405Sjkim 326280304Sjkim /* 327280304Sjkim * now for the fun part ... if we have a private key then we have to be 328280304Sjkim * able to handle a not-yet-decrypted key being written out correctly ... 329280304Sjkim * if it is decrypted or it is non-encrypted then we use the base code 330280304Sjkim */ 331280304Sjkim if (xi->x_pkey != NULL) { 332280304Sjkim if ((xi->enc_data != NULL) && (xi->enc_len > 0)) { 333280304Sjkim if (enc == NULL) { 334280304Sjkim PEMerr(PEM_F_PEM_X509_INFO_WRITE_BIO, PEM_R_CIPHER_IS_NULL); 335280304Sjkim goto err; 336280304Sjkim } 33755714Skris 338280304Sjkim /* copy from weirdo names into more normal things */ 339280304Sjkim iv = xi->enc_cipher.iv; 340280304Sjkim data = (unsigned char *)xi->enc_data; 341280304Sjkim i = xi->enc_len; 34255714Skris 343280304Sjkim /* 344280304Sjkim * we take the encryption data from the internal stuff rather 345280304Sjkim * than what the user has passed us ... as we have to match 346280304Sjkim * exactly for some strange reason 347280304Sjkim */ 348280304Sjkim objstr = OBJ_nid2sn(EVP_CIPHER_nid(xi->enc_cipher.cipher)); 349280304Sjkim if (objstr == NULL) { 350280304Sjkim PEMerr(PEM_F_PEM_X509_INFO_WRITE_BIO, 351280304Sjkim PEM_R_UNSUPPORTED_CIPHER); 352280304Sjkim goto err; 353280304Sjkim } 35455714Skris 355280304Sjkim /* create the right magic header stuff */ 356280304Sjkim OPENSSL_assert(strlen(objstr) + 23 + 2 * enc->iv_len + 13 <= 357280304Sjkim sizeof buf); 358280304Sjkim buf[0] = '\0'; 359280304Sjkim PEM_proc_type(buf, PEM_TYPE_ENCRYPTED); 360280304Sjkim PEM_dek_info(buf, objstr, enc->iv_len, (char *)iv); 361280304Sjkim 362280304Sjkim /* use the normal code to write things out */ 363280304Sjkim i = PEM_write_bio(bp, PEM_STRING_RSA, buf, data, i); 364280304Sjkim if (i <= 0) 365280304Sjkim goto err; 366280304Sjkim } else { 367280304Sjkim /* Add DSA/DH */ 368109998Smarkm#ifndef OPENSSL_NO_RSA 369280304Sjkim /* normal optionally encrypted stuff */ 370280304Sjkim if (PEM_write_bio_RSAPrivateKey(bp, 371280304Sjkim xi->x_pkey->dec_pkey->pkey.rsa, 372280304Sjkim enc, kstr, klen, cb, u) <= 0) 373280304Sjkim goto err; 37455714Skris#endif 375280304Sjkim } 376280304Sjkim } 37755714Skris 378280304Sjkim /* if we have a certificate then write it out now */ 379280304Sjkim if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp, xi->x509) <= 0)) 380280304Sjkim goto err; 38155714Skris 382280304Sjkim /* 383280304Sjkim * we are ignoring anything else that is loaded into the X509_INFO 384280304Sjkim * structure for the moment ... as I don't need it so I'm not coding it 385280304Sjkim * here and Eric can do it when this makes it into the base library --tjh 386280304Sjkim */ 38755714Skris 388280304Sjkim ret = 1; 38955714Skris 390280304Sjkim err: 391280304Sjkim OPENSSL_cleanse((char *)&ctx, sizeof(ctx)); 392280304Sjkim OPENSSL_cleanse(buf, PEM_BUFSIZE); 393280304Sjkim return (ret); 394280304Sjkim} 395