/src/openssl111/crypto/pem/pem_pkey.c
Line | Count | Source (jump to first uncovered line) |
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 | 0 | { |
28 | 0 | char *nm = NULL; |
29 | 0 | const unsigned char *p = NULL; |
30 | 0 | unsigned char *data = NULL; |
31 | 0 | long len; |
32 | 0 | int slen; |
33 | 0 | EVP_PKEY *ret = NULL; |
34 | |
|
35 | 0 | if (!PEM_bytes_read_bio_secmem(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, |
36 | 0 | cb, u)) |
37 | 0 | return NULL; |
38 | 0 | p = data; |
39 | |
|
40 | 0 | if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) { |
41 | 0 | PKCS8_PRIV_KEY_INFO *p8inf; |
42 | 0 | p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len); |
43 | 0 | if (!p8inf) |
44 | 0 | goto p8err; |
45 | 0 | ret = EVP_PKCS82PKEY(p8inf); |
46 | 0 | if (x) { |
47 | 0 | EVP_PKEY_free((EVP_PKEY *)*x); |
48 | 0 | *x = ret; |
49 | 0 | } |
50 | 0 | PKCS8_PRIV_KEY_INFO_free(p8inf); |
51 | 0 | } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) { |
52 | 0 | PKCS8_PRIV_KEY_INFO *p8inf; |
53 | 0 | X509_SIG *p8; |
54 | 0 | int klen; |
55 | 0 | char psbuf[PEM_BUFSIZE]; |
56 | 0 | p8 = d2i_X509_SIG(NULL, &p, len); |
57 | 0 | if (!p8) |
58 | 0 | goto p8err; |
59 | 0 | if (cb) |
60 | 0 | klen = cb(psbuf, PEM_BUFSIZE, 0, u); |
61 | 0 | else |
62 | 0 | klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u); |
63 | 0 | if (klen < 0) { |
64 | 0 | PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, PEM_R_BAD_PASSWORD_READ); |
65 | 0 | X509_SIG_free(p8); |
66 | 0 | goto err; |
67 | 0 | } |
68 | 0 | p8inf = PKCS8_decrypt(p8, psbuf, klen); |
69 | 0 | X509_SIG_free(p8); |
70 | 0 | OPENSSL_cleanse(psbuf, klen); |
71 | 0 | if (!p8inf) |
72 | 0 | goto p8err; |
73 | 0 | ret = EVP_PKCS82PKEY(p8inf); |
74 | 0 | if (x) { |
75 | 0 | EVP_PKEY_free((EVP_PKEY *)*x); |
76 | 0 | *x = ret; |
77 | 0 | } |
78 | 0 | PKCS8_PRIV_KEY_INFO_free(p8inf); |
79 | 0 | } else if ((slen = pem_check_suffix(nm, "PRIVATE KEY")) > 0) { |
80 | 0 | const EVP_PKEY_ASN1_METHOD *ameth; |
81 | 0 | ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen); |
82 | 0 | if (!ameth || !ameth->old_priv_decode) |
83 | 0 | goto p8err; |
84 | 0 | ret = d2i_PrivateKey(ameth->pkey_id, x, &p, len); |
85 | 0 | } |
86 | 0 | p8err: |
87 | 0 | if (ret == NULL) |
88 | 0 | PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, ERR_R_ASN1_LIB); |
89 | 0 | err: |
90 | 0 | OPENSSL_secure_free(nm); |
91 | 0 | OPENSSL_secure_clear_free(data, len); |
92 | 0 | return ret; |
93 | 0 | } |
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 | 0 | { |
99 | 0 | if (x->ameth == NULL || x->ameth->priv_encode != NULL) |
100 | 0 | return PEM_write_bio_PKCS8PrivateKey(bp, x, enc, |
101 | 0 | (char *)kstr, klen, cb, u); |
102 | 0 | return PEM_write_bio_PrivateKey_traditional(bp, x, enc, kstr, klen, cb, u); |
103 | 0 | } |
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 | 0 | { |
110 | 0 | char pem_str[80]; |
111 | |
|
112 | 0 | if (x->ameth == NULL || x->ameth->old_priv_encode == NULL) { |
113 | 0 | PEMerr(PEM_F_PEM_WRITE_BIO_PRIVATEKEY_TRADITIONAL, |
114 | 0 | PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE); |
115 | 0 | return 0; |
116 | 0 | } |
117 | 0 | BIO_snprintf(pem_str, 80, "%s PRIVATE KEY", x->ameth->pem_str); |
118 | 0 | return PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey, |
119 | 0 | pem_str, bp, x, enc, kstr, klen, cb, u); |
120 | 0 | } |
121 | | |
122 | | EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x) |
123 | 0 | { |
124 | 0 | char *nm = NULL; |
125 | 0 | const unsigned char *p = NULL; |
126 | 0 | unsigned char *data = NULL; |
127 | 0 | long len; |
128 | 0 | int slen; |
129 | 0 | EVP_PKEY *ret = NULL; |
130 | |
|
131 | 0 | if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_PARAMETERS, |
132 | 0 | bp, 0, NULL)) |
133 | 0 | return NULL; |
134 | 0 | p = data; |
135 | |
|
136 | 0 | if ((slen = pem_check_suffix(nm, "PARAMETERS")) > 0) { |
137 | 0 | ret = EVP_PKEY_new(); |
138 | 0 | if (ret == NULL) |
139 | 0 | goto err; |
140 | 0 | if (!EVP_PKEY_set_type_str(ret, nm, slen) |
141 | 0 | || !ret->ameth->param_decode |
142 | 0 | || !ret->ameth->param_decode(ret, &p, len)) { |
143 | 0 | EVP_PKEY_free(ret); |
144 | 0 | ret = NULL; |
145 | 0 | goto err; |
146 | 0 | } |
147 | 0 | if (x) { |
148 | 0 | EVP_PKEY_free((EVP_PKEY *)*x); |
149 | 0 | *x = ret; |
150 | 0 | } |
151 | 0 | } |
152 | 0 | err: |
153 | 0 | if (ret == NULL) |
154 | 0 | PEMerr(PEM_F_PEM_READ_BIO_PARAMETERS, ERR_R_ASN1_LIB); |
155 | 0 | OPENSSL_free(nm); |
156 | 0 | OPENSSL_free(data); |
157 | 0 | return ret; |
158 | 0 | } |
159 | | |
160 | | int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x) |
161 | 0 | { |
162 | 0 | char pem_str[80]; |
163 | 0 | if (!x->ameth || !x->ameth->param_encode) |
164 | 0 | return 0; |
165 | | |
166 | 0 | BIO_snprintf(pem_str, 80, "%s PARAMETERS", x->ameth->pem_str); |
167 | 0 | return PEM_ASN1_write_bio((i2d_of_void *)x->ameth->param_encode, |
168 | 0 | pem_str, bp, x, NULL, NULL, 0, 0, NULL); |
169 | 0 | } |
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 | 0 | { |
175 | 0 | BIO *b; |
176 | 0 | EVP_PKEY *ret; |
177 | |
|
178 | 0 | if ((b = BIO_new(BIO_s_file())) == NULL) { |
179 | 0 | PEMerr(PEM_F_PEM_READ_PRIVATEKEY, ERR_R_BUF_LIB); |
180 | 0 | return 0; |
181 | 0 | } |
182 | 0 | BIO_set_fp(b, fp, BIO_NOCLOSE); |
183 | 0 | ret = PEM_read_bio_PrivateKey(b, x, cb, u); |
184 | 0 | BIO_free(b); |
185 | 0 | return ret; |
186 | 0 | } |
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 | 0 | { |
192 | 0 | BIO *b; |
193 | 0 | int ret; |
194 | |
|
195 | 0 | if ((b = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) { |
196 | 0 | PEMerr(PEM_F_PEM_WRITE_PRIVATEKEY, ERR_R_BUF_LIB); |
197 | 0 | return 0; |
198 | 0 | } |
199 | 0 | ret = PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u); |
200 | 0 | BIO_free(b); |
201 | 0 | return ret; |
202 | 0 | } |
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 | 0 | { |
212 | 0 | char *nm = NULL; |
213 | 0 | const unsigned char *p = NULL; |
214 | 0 | unsigned char *data = NULL; |
215 | 0 | long len; |
216 | 0 | DH *ret = NULL; |
217 | |
|
218 | 0 | if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_DHPARAMS, bp, cb, u)) |
219 | 0 | return NULL; |
220 | 0 | p = data; |
221 | |
|
222 | 0 | if (strcmp(nm, PEM_STRING_DHXPARAMS) == 0) |
223 | 0 | ret = d2i_DHxparams(x, &p, len); |
224 | 0 | else |
225 | 0 | ret = d2i_DHparams(x, &p, len); |
226 | |
|
227 | 0 | if (ret == NULL) |
228 | 0 | PEMerr(PEM_F_PEM_READ_BIO_DHPARAMS, ERR_R_ASN1_LIB); |
229 | 0 | OPENSSL_free(nm); |
230 | 0 | OPENSSL_free(data); |
231 | 0 | return ret; |
232 | 0 | } |
233 | | |
234 | | # ifndef OPENSSL_NO_STDIO |
235 | | DH *PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u) |
236 | 0 | { |
237 | 0 | BIO *b; |
238 | 0 | DH *ret; |
239 | |
|
240 | 0 | if ((b = BIO_new(BIO_s_file())) == NULL) { |
241 | 0 | PEMerr(PEM_F_PEM_READ_DHPARAMS, ERR_R_BUF_LIB); |
242 | 0 | return 0; |
243 | 0 | } |
244 | 0 | BIO_set_fp(b, fp, BIO_NOCLOSE); |
245 | 0 | ret = PEM_read_bio_DHparams(b, x, cb, u); |
246 | 0 | BIO_free(b); |
247 | 0 | return ret; |
248 | 0 | } |
249 | | # endif |
250 | | |
251 | | #endif |