Home | History | Annotate | Line # | Download | only in pem
      1 /*
      2  * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the OpenSSL license (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 #include <stdio.h>
     11 #include "internal/cryptlib.h"
     12 #include <openssl/buffer.h>
     13 #include <openssl/objects.h>
     14 #include <openssl/evp.h>
     15 #include <openssl/x509.h>
     16 #include <openssl/pkcs12.h>
     17 #include <openssl/pem.h>
     18 #include <openssl/engine.h>
     19 #include <openssl/dh.h>
     20 #include "crypto/asn1.h"
     21 #include "crypto/evp.h"
     22 
     23 int pem_check_suffix(const char *pem_str, const char *suffix);
     24 
     25 EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
     26                                   void *u)
     27 {
     28     char *nm = NULL;
     29     const unsigned char *p = NULL;
     30     unsigned char *data = NULL;
     31     long len;
     32     int slen;
     33     EVP_PKEY *ret = NULL;
     34 
     35     if (!PEM_bytes_read_bio_secmem(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp,
     36                                    cb, u))
     37         return NULL;
     38     p = data;
     39 
     40     if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) {
     41         PKCS8_PRIV_KEY_INFO *p8inf;
     42         p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
     43         if (!p8inf)
     44             goto p8err;
     45         ret = EVP_PKCS82PKEY(p8inf);
     46         if (x) {
     47             EVP_PKEY_free((EVP_PKEY *)*x);
     48             *x = ret;
     49         }
     50         PKCS8_PRIV_KEY_INFO_free(p8inf);
     51     } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) {
     52         PKCS8_PRIV_KEY_INFO *p8inf;
     53         X509_SIG *p8;
     54         int klen;
     55         char psbuf[PEM_BUFSIZE];
     56         p8 = d2i_X509_SIG(NULL, &p, len);
     57         if (!p8)
     58             goto p8err;
     59         if (cb)
     60             klen = cb(psbuf, PEM_BUFSIZE, 0, u);
     61         else
     62             klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
     63         if (klen < 0) {
     64             PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, PEM_R_BAD_PASSWORD_READ);
     65             X509_SIG_free(p8);
     66             goto err;
     67         }
     68         p8inf = PKCS8_decrypt(p8, psbuf, klen);
     69         X509_SIG_free(p8);
     70         OPENSSL_cleanse(psbuf, klen);
     71         if (!p8inf)
     72             goto p8err;
     73         ret = EVP_PKCS82PKEY(p8inf);
     74         if (x) {
     75             EVP_PKEY_free((EVP_PKEY *)*x);
     76             *x = ret;
     77         }
     78         PKCS8_PRIV_KEY_INFO_free(p8inf);
     79     } else if ((slen = pem_check_suffix(nm, "PRIVATE KEY")) > 0) {
     80         const EVP_PKEY_ASN1_METHOD *ameth;
     81         ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen);
     82         if (!ameth || !ameth->old_priv_decode)
     83             goto p8err;
     84         ret = d2i_PrivateKey(ameth->pkey_id, x, &p, len);
     85     }
     86  p8err:
     87     if (ret == NULL)
     88         PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, ERR_R_ASN1_LIB);
     89  err:
     90     OPENSSL_secure_free(nm);
     91     OPENSSL_secure_clear_free(data, len);
     92     return ret;
     93 }
     94 
     95 int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
     96                              unsigned char *kstr, int klen,
     97                              pem_password_cb *cb, void *u)
     98 {
     99     if (x->ameth == NULL || x->ameth->priv_encode != NULL)
    100         return PEM_write_bio_PKCS8PrivateKey(bp, x, enc,
    101                                              (char *)kstr, klen, cb, u);
    102     return PEM_write_bio_PrivateKey_traditional(bp, x, enc, kstr, klen, cb, u);
    103 }
    104 
    105 int PEM_write_bio_PrivateKey_traditional(BIO *bp, EVP_PKEY *x,
    106                                          const EVP_CIPHER *enc,
    107                                          unsigned char *kstr, int klen,
    108                                          pem_password_cb *cb, void *u)
    109 {
    110     char pem_str[80];
    111 
    112     if (x->ameth == NULL || x->ameth->old_priv_encode == NULL) {
    113         PEMerr(PEM_F_PEM_WRITE_BIO_PRIVATEKEY_TRADITIONAL,
    114                PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
    115         return 0;
    116     }
    117     BIO_snprintf(pem_str, 80, "%s PRIVATE KEY", x->ameth->pem_str);
    118     return PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey,
    119                               pem_str, bp, x, enc, kstr, klen, cb, u);
    120 }
    121 
    122 EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x)
    123 {
    124     char *nm = NULL;
    125     const unsigned char *p = NULL;
    126     unsigned char *data = NULL;
    127     long len;
    128     int slen;
    129     EVP_PKEY *ret = NULL;
    130 
    131     if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_PARAMETERS,
    132                             bp, 0, NULL))
    133         return NULL;
    134     p = data;
    135 
    136     if ((slen = pem_check_suffix(nm, "PARAMETERS")) > 0) {
    137         ret = EVP_PKEY_new();
    138         if (ret == NULL)
    139             goto err;
    140         if (!EVP_PKEY_set_type_str(ret, nm, slen)
    141             || !ret->ameth->param_decode
    142             || !ret->ameth->param_decode(ret, &p, len)) {
    143             EVP_PKEY_free(ret);
    144             ret = NULL;
    145             goto err;
    146         }
    147         if (x) {
    148             EVP_PKEY_free((EVP_PKEY *)*x);
    149             *x = ret;
    150         }
    151     }
    152  err:
    153     if (ret == NULL)
    154         PEMerr(PEM_F_PEM_READ_BIO_PARAMETERS, ERR_R_ASN1_LIB);
    155     OPENSSL_free(nm);
    156     OPENSSL_free(data);
    157     return ret;
    158 }
    159 
    160 int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x)
    161 {
    162     char pem_str[80];
    163     if (!x->ameth || !x->ameth->param_encode)
    164         return 0;
    165 
    166     BIO_snprintf(pem_str, 80, "%s PARAMETERS", x->ameth->pem_str);
    167     return PEM_ASN1_write_bio((i2d_of_void *)x->ameth->param_encode,
    168                               pem_str, bp, x, NULL, NULL, 0, 0, NULL);
    169 }
    170 
    171 #ifndef OPENSSL_NO_STDIO
    172 EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
    173                               void *u)
    174 {
    175     BIO *b;
    176     EVP_PKEY *ret;
    177 
    178     if ((b = BIO_new(BIO_s_file())) == NULL) {
    179         PEMerr(PEM_F_PEM_READ_PRIVATEKEY, ERR_R_BUF_LIB);
    180         return 0;
    181     }
    182     BIO_set_fp(b, fp, BIO_NOCLOSE);
    183     ret = PEM_read_bio_PrivateKey(b, x, cb, u);
    184     BIO_free(b);
    185     return ret;
    186 }
    187 
    188 int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
    189                          unsigned char *kstr, int klen,
    190                          pem_password_cb *cb, void *u)
    191 {
    192     BIO *b;
    193     int ret;
    194 
    195     if ((b = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
    196         PEMerr(PEM_F_PEM_WRITE_PRIVATEKEY, ERR_R_BUF_LIB);
    197         return 0;
    198     }
    199     ret = PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u);
    200     BIO_free(b);
    201     return ret;
    202 }
    203 
    204 #endif
    205 
    206 #ifndef OPENSSL_NO_DH
    207 
    208 /* Transparently read in PKCS#3 or X9.42 DH parameters */
    209 
    210 DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u)
    211 {
    212     char *nm = NULL;
    213     const unsigned char *p = NULL;
    214     unsigned char *data = NULL;
    215     long len;
    216     DH *ret = NULL;
    217 
    218     if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_DHPARAMS, bp, cb, u))
    219         return NULL;
    220     p = data;
    221 
    222     if (strcmp(nm, PEM_STRING_DHXPARAMS) == 0)
    223         ret = d2i_DHxparams(x, &p, len);
    224     else
    225         ret = d2i_DHparams(x, &p, len);
    226 
    227     if (ret == NULL)
    228         PEMerr(PEM_F_PEM_READ_BIO_DHPARAMS, ERR_R_ASN1_LIB);
    229     OPENSSL_free(nm);
    230     OPENSSL_free(data);
    231     return ret;
    232 }
    233 
    234 # ifndef OPENSSL_NO_STDIO
    235 DH *PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u)
    236 {
    237     BIO *b;
    238     DH *ret;
    239 
    240     if ((b = BIO_new(BIO_s_file())) == NULL) {
    241         PEMerr(PEM_F_PEM_READ_DHPARAMS, ERR_R_BUF_LIB);
    242         return 0;
    243     }
    244     BIO_set_fp(b, fp, BIO_NOCLOSE);
    245     ret = PEM_read_bio_DHparams(b, x, cb, u);
    246     BIO_free(b);
    247     return ret;
    248 }
    249 # endif
    250 
    251 #endif
    252