Coverage Report

Created: 2025-06-11 06:41

/src/boringssl/crypto/pem/pem_pkey.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include <openssl/pem.h>
16
17
#include <stdio.h>
18
#include <string.h>
19
20
#include <openssl/dh.h>
21
#include <openssl/err.h>
22
#include <openssl/evp.h>
23
#include <openssl/mem.h>
24
#include <openssl/obj.h>
25
#include <openssl/pkcs8.h>
26
#include <openssl/rand.h>
27
#include <openssl/x509.h>
28
29
EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
30
0
                                  void *u) {
31
0
  char *nm = NULL;
32
0
  const unsigned char *p = NULL;
33
0
  unsigned char *data = NULL;
34
0
  long len;
35
0
  EVP_PKEY *ret = NULL;
36
37
0
  if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u)) {
38
0
    return NULL;
39
0
  }
40
0
  p = data;
41
42
0
  if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) {
43
0
    PKCS8_PRIV_KEY_INFO *p8inf;
44
0
    p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
45
0
    if (!p8inf) {
46
0
      goto p8err;
47
0
    }
48
0
    ret = EVP_PKCS82PKEY(p8inf);
49
0
    if (x) {
50
0
      if (*x) {
51
0
        EVP_PKEY_free((EVP_PKEY *)*x);
52
0
      }
53
0
      *x = ret;
54
0
    }
55
0
    PKCS8_PRIV_KEY_INFO_free(p8inf);
56
0
  } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) {
57
0
    PKCS8_PRIV_KEY_INFO *p8inf;
58
0
    X509_SIG *p8;
59
0
    int pass_len;
60
0
    char psbuf[PEM_BUFSIZE];
61
0
    p8 = d2i_X509_SIG(NULL, &p, len);
62
0
    if (!p8) {
63
0
      goto p8err;
64
0
    }
65
66
0
    pass_len = 0;
67
0
    if (!cb) {
68
0
      cb = PEM_def_callback;
69
0
    }
70
0
    pass_len = cb(psbuf, PEM_BUFSIZE, 0, u);
71
0
    if (pass_len < 0) {
72
0
      OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ);
73
0
      X509_SIG_free(p8);
74
0
      goto err;
75
0
    }
76
0
    p8inf = PKCS8_decrypt(p8, psbuf, pass_len);
77
0
    X509_SIG_free(p8);
78
0
    OPENSSL_cleanse(psbuf, pass_len);
79
0
    if (!p8inf) {
80
0
      goto p8err;
81
0
    }
82
0
    ret = EVP_PKCS82PKEY(p8inf);
83
0
    if (x) {
84
0
      if (*x) {
85
0
        EVP_PKEY_free((EVP_PKEY *)*x);
86
0
      }
87
0
      *x = ret;
88
0
    }
89
0
    PKCS8_PRIV_KEY_INFO_free(p8inf);
90
0
  } else if (strcmp(nm, PEM_STRING_RSA) == 0) {
91
    // TODO(davidben): d2i_PrivateKey parses PKCS#8 along with the
92
    // standalone format. This and the cases below probably should not
93
    // accept PKCS#8.
94
0
    ret = d2i_PrivateKey(EVP_PKEY_RSA, x, &p, len);
95
0
  } else if (strcmp(nm, PEM_STRING_EC) == 0) {
96
0
    ret = d2i_PrivateKey(EVP_PKEY_EC, x, &p, len);
97
0
  } else if (strcmp(nm, PEM_STRING_DSA) == 0) {
98
0
    ret = d2i_PrivateKey(EVP_PKEY_DSA, x, &p, len);
99
0
  }
100
0
p8err:
101
0
  if (ret == NULL) {
102
0
    OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
103
0
  }
104
105
0
err:
106
0
  OPENSSL_free(nm);
107
0
  OPENSSL_free(data);
108
0
  return ret;
109
0
}
110
111
int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
112
                             const unsigned char *pass, int pass_len,
113
0
                             pem_password_cb *cb, void *u) {
114
0
  return PEM_write_bio_PKCS8PrivateKey(bp, x, enc, (const char *)pass, pass_len,
115
0
                                       cb, u);
116
0
}
117
118
EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
119
0
                              void *u) {
120
0
  BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
121
0
  if (b == NULL) {
122
0
    OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
123
0
    return NULL;
124
0
  }
125
0
  EVP_PKEY *ret = PEM_read_bio_PrivateKey(b, x, cb, u);
126
0
  BIO_free(b);
127
0
  return ret;
128
0
}
129
130
int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
131
                         const unsigned char *pass, int pass_len,
132
0
                         pem_password_cb *cb, void *u) {
133
0
  BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
134
0
  if (b == NULL) {
135
0
    OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
136
0
    return 0;
137
0
  }
138
0
  int ret = PEM_write_bio_PrivateKey(b, x, enc, pass, pass_len, cb, u);
139
0
  BIO_free(b);
140
0
  return ret;
141
0
}