/src/openssl/crypto/pem/pem_pkey.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 1995-2018 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 "internal/asn1_int.h" |
21 | | #include "internal/evp_int.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 | 202k | { |
28 | 202k | char *nm = NULL; |
29 | 202k | const unsigned char *p = NULL; |
30 | 202k | unsigned char *data = NULL; |
31 | 202k | long len; |
32 | 202k | int slen; |
33 | 202k | EVP_PKEY *ret = NULL; |
34 | 202k | |
35 | 202k | if (!PEM_bytes_read_bio_secmem(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, |
36 | 202k | cb, u)) |
37 | 15.4k | return NULL; |
38 | 187k | p = data; |
39 | 187k | |
40 | 187k | 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 | 187k | } 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 | 187k | } else if ((slen = pem_check_suffix(nm, "PRIVATE KEY")) > 0) { |
80 | 187k | const EVP_PKEY_ASN1_METHOD *ameth; |
81 | 187k | ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen); |
82 | 187k | if (!ameth || !ameth->old_priv_decode) |
83 | 0 | goto p8err; |
84 | 187k | ret = d2i_PrivateKey(ameth->pkey_id, x, &p, len); |
85 | 187k | } |
86 | 187k | p8err: |
87 | 187k | if (ret == NULL) |
88 | 187k | PEMerr(PEM_F_PEM_READ_BIO_PRIVATEKEY, ERR_R_ASN1_LIB); |
89 | 187k | err: |
90 | 187k | OPENSSL_secure_free(nm); |
91 | 187k | OPENSSL_secure_clear_free(data, len); |
92 | 187k | return ret; |
93 | 187k | } |
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 | 0 | BIO_snprintf(pem_str, 80, "%s PRIVATE KEY", x->ameth->pem_str); |
112 | 0 | return PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey, |
113 | 0 | pem_str, bp, x, enc, kstr, klen, cb, u); |
114 | 0 | } |
115 | | |
116 | | EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x) |
117 | 0 | { |
118 | 0 | char *nm = NULL; |
119 | 0 | const unsigned char *p = NULL; |
120 | 0 | unsigned char *data = NULL; |
121 | 0 | long len; |
122 | 0 | int slen; |
123 | 0 | EVP_PKEY *ret = NULL; |
124 | 0 |
|
125 | 0 | if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_PARAMETERS, |
126 | 0 | bp, 0, NULL)) |
127 | 0 | return NULL; |
128 | 0 | p = data; |
129 | 0 |
|
130 | 0 | if ((slen = pem_check_suffix(nm, "PARAMETERS")) > 0) { |
131 | 0 | ret = EVP_PKEY_new(); |
132 | 0 | if (ret == NULL) |
133 | 0 | goto err; |
134 | 0 | if (!EVP_PKEY_set_type_str(ret, nm, slen) |
135 | 0 | || !ret->ameth->param_decode |
136 | 0 | || !ret->ameth->param_decode(ret, &p, len)) { |
137 | 0 | EVP_PKEY_free(ret); |
138 | 0 | ret = NULL; |
139 | 0 | goto err; |
140 | 0 | } |
141 | 0 | if (x) { |
142 | 0 | EVP_PKEY_free((EVP_PKEY *)*x); |
143 | 0 | *x = ret; |
144 | 0 | } |
145 | 0 | } |
146 | 0 | err: |
147 | 0 | if (ret == NULL) |
148 | 0 | PEMerr(PEM_F_PEM_READ_BIO_PARAMETERS, ERR_R_ASN1_LIB); |
149 | 0 | OPENSSL_free(nm); |
150 | 0 | OPENSSL_free(data); |
151 | 0 | return ret; |
152 | 0 | } |
153 | | |
154 | | int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x) |
155 | 0 | { |
156 | 0 | char pem_str[80]; |
157 | 0 | if (!x->ameth || !x->ameth->param_encode) |
158 | 0 | return 0; |
159 | 0 | |
160 | 0 | BIO_snprintf(pem_str, 80, "%s PARAMETERS", x->ameth->pem_str); |
161 | 0 | return PEM_ASN1_write_bio((i2d_of_void *)x->ameth->param_encode, |
162 | 0 | pem_str, bp, x, NULL, NULL, 0, 0, NULL); |
163 | 0 | } |
164 | | |
165 | | #ifndef OPENSSL_NO_STDIO |
166 | | EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, |
167 | | void *u) |
168 | 0 | { |
169 | 0 | BIO *b; |
170 | 0 | EVP_PKEY *ret; |
171 | 0 |
|
172 | 0 | if ((b = BIO_new(BIO_s_file())) == NULL) { |
173 | 0 | PEMerr(PEM_F_PEM_READ_PRIVATEKEY, ERR_R_BUF_LIB); |
174 | 0 | return 0; |
175 | 0 | } |
176 | 0 | BIO_set_fp(b, fp, BIO_NOCLOSE); |
177 | 0 | ret = PEM_read_bio_PrivateKey(b, x, cb, u); |
178 | 0 | BIO_free(b); |
179 | 0 | return ret; |
180 | 0 | } |
181 | | |
182 | | int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, |
183 | | unsigned char *kstr, int klen, |
184 | | pem_password_cb *cb, void *u) |
185 | 0 | { |
186 | 0 | BIO *b; |
187 | 0 | int ret; |
188 | 0 |
|
189 | 0 | if ((b = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) { |
190 | 0 | PEMerr(PEM_F_PEM_WRITE_PRIVATEKEY, ERR_R_BUF_LIB); |
191 | 0 | return 0; |
192 | 0 | } |
193 | 0 | ret = PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u); |
194 | 0 | BIO_free(b); |
195 | 0 | return ret; |
196 | 0 | } |
197 | | |
198 | | #endif |
199 | | |
200 | | #ifndef OPENSSL_NO_DH |
201 | | |
202 | | /* Transparently read in PKCS#3 or X9.42 DH parameters */ |
203 | | |
204 | | DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u) |
205 | | { |
206 | | char *nm = NULL; |
207 | | const unsigned char *p = NULL; |
208 | | unsigned char *data = NULL; |
209 | | long len; |
210 | | DH *ret = NULL; |
211 | | |
212 | | if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_DHPARAMS, bp, cb, u)) |
213 | | return NULL; |
214 | | p = data; |
215 | | |
216 | | if (strcmp(nm, PEM_STRING_DHXPARAMS) == 0) |
217 | | ret = d2i_DHxparams(x, &p, len); |
218 | | else |
219 | | ret = d2i_DHparams(x, &p, len); |
220 | | |
221 | | if (ret == NULL) |
222 | | PEMerr(PEM_F_PEM_READ_BIO_DHPARAMS, ERR_R_ASN1_LIB); |
223 | | OPENSSL_free(nm); |
224 | | OPENSSL_free(data); |
225 | | return ret; |
226 | | } |
227 | | |
228 | | # ifndef OPENSSL_NO_STDIO |
229 | | DH *PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u) |
230 | 0 | { |
231 | 0 | BIO *b; |
232 | 0 | DH *ret; |
233 | 0 |
|
234 | 0 | if ((b = BIO_new(BIO_s_file())) == NULL) { |
235 | 0 | PEMerr(PEM_F_PEM_READ_DHPARAMS, ERR_R_BUF_LIB); |
236 | 0 | return 0; |
237 | 0 | } |
238 | 0 | BIO_set_fp(b, fp, BIO_NOCLOSE); |
239 | 0 | ret = PEM_read_bio_DHparams(b, x, cb, u); |
240 | 0 | BIO_free(b); |
241 | 0 | return ret; |
242 | 0 | } |
243 | | # endif |
244 | | |
245 | | #endif |