/src/boringssl/crypto/pkcs8/p5_pbev2.cc
Line | Count | Source |
1 | | // Copyright 1999-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/pkcs8.h> |
16 | | |
17 | | #include <limits.h> |
18 | | #include <string.h> |
19 | | |
20 | | #include <openssl/bytestring.h> |
21 | | #include <openssl/cipher.h> |
22 | | #include <openssl/digest.h> |
23 | | #include <openssl/err.h> |
24 | | #include <openssl/mem.h> |
25 | | #include <openssl/nid.h> |
26 | | #include <openssl/rand.h> |
27 | | |
28 | | #include "../internal.h" |
29 | | #include "internal.h" |
30 | | |
31 | | |
32 | | using namespace bssl; |
33 | | |
34 | | // 1.2.840.113549.1.5.12 |
35 | | static const uint8_t kPBKDF2[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, |
36 | | 0x0d, 0x01, 0x05, 0x0c}; |
37 | | |
38 | | // 1.2.840.113549.1.5.13 |
39 | | static const uint8_t kPBES2[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, |
40 | | 0x0d, 0x01, 0x05, 0x0d}; |
41 | | |
42 | | // 1.2.840.113549.2.7 |
43 | | static const uint8_t kHMACWithSHA1[] = {0x2a, 0x86, 0x48, 0x86, |
44 | | 0xf7, 0x0d, 0x02, 0x07}; |
45 | | |
46 | | // 1.2.840.113549.2.9 |
47 | | static const uint8_t kHMACWithSHA256[] = {0x2a, 0x86, 0x48, 0x86, |
48 | | 0xf7, 0x0d, 0x02, 0x09}; |
49 | | |
50 | | static const struct { |
51 | | uint8_t oid[9]; |
52 | | uint8_t oid_len; |
53 | | int nid; |
54 | | const EVP_CIPHER *(*cipher_func)(); |
55 | | } kCipherOIDs[] = { |
56 | | // 1.2.840.113549.3.2 |
57 | | {{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x02}, |
58 | | 8, |
59 | | NID_rc2_cbc, |
60 | | &EVP_rc2_cbc}, |
61 | | // 1.2.840.113549.3.7 |
62 | | {{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07}, |
63 | | 8, |
64 | | NID_des_ede3_cbc, |
65 | | &EVP_des_ede3_cbc}, |
66 | | // 2.16.840.1.101.3.4.1.2 |
67 | | {{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02}, |
68 | | 9, |
69 | | NID_aes_128_cbc, |
70 | | &EVP_aes_128_cbc}, |
71 | | // 2.16.840.1.101.3.4.1.22 |
72 | | {{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x16}, |
73 | | 9, |
74 | | NID_aes_192_cbc, |
75 | | &EVP_aes_192_cbc}, |
76 | | // 2.16.840.1.101.3.4.1.42 |
77 | | {{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2a}, |
78 | | 9, |
79 | | NID_aes_256_cbc, |
80 | | &EVP_aes_256_cbc}, |
81 | | }; |
82 | | |
83 | 2 | static const EVP_CIPHER *cbs_to_cipher(const CBS *cbs) { |
84 | 6 | for (const auto &cipher : kCipherOIDs) { |
85 | 6 | if (CBS_mem_equal(cbs, cipher.oid, cipher.oid_len)) { |
86 | 2 | return cipher.cipher_func(); |
87 | 2 | } |
88 | 6 | } |
89 | | |
90 | 0 | return nullptr; |
91 | 2 | } |
92 | | |
93 | 0 | static int add_cipher_oid(CBB *out, int nid) { |
94 | 0 | for (const auto &cipher : kCipherOIDs) { |
95 | 0 | if (cipher.nid == nid) { |
96 | 0 | return CBB_add_asn1_element(out, CBS_ASN1_OBJECT, cipher.oid, |
97 | 0 | cipher.oid_len); |
98 | 0 | } |
99 | 0 | } |
100 | | |
101 | 0 | OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_CIPHER); |
102 | 0 | return 0; |
103 | 0 | } |
104 | | |
105 | 0 | const EVP_CIPHER *bssl::pkcs5_pbe2_nid_to_cipher(int nid) { |
106 | 0 | for (const auto &cipher : kCipherOIDs) { |
107 | 0 | if (cipher.nid == nid) { |
108 | 0 | return cipher.cipher_func(); |
109 | 0 | } |
110 | 0 | } |
111 | 0 | return nullptr; |
112 | 0 | } |
113 | | |
114 | | static int pkcs5_pbe2_cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, |
115 | | const EVP_MD *pbkdf2_md, uint32_t iterations, |
116 | | const char *pass, size_t pass_len, |
117 | | const uint8_t *salt, size_t salt_len, |
118 | 2 | const uint8_t *iv, size_t iv_len, int enc) { |
119 | 2 | if (iv_len != EVP_CIPHER_iv_length(cipher)) { |
120 | 0 | OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS); |
121 | 0 | return 0; |
122 | 0 | } |
123 | | |
124 | 2 | uint8_t key[EVP_MAX_KEY_LENGTH]; |
125 | 2 | int ret = PKCS5_PBKDF2_HMAC(pass, pass_len, salt, salt_len, iterations, |
126 | 2 | pbkdf2_md, EVP_CIPHER_key_length(cipher), key) && |
127 | 2 | EVP_CipherInit_ex(ctx, cipher, nullptr /* engine */, key, iv, enc); |
128 | 2 | OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH); |
129 | 2 | return ret; |
130 | 2 | } |
131 | | |
132 | | int bssl::PKCS5_pbe2_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx, |
133 | | const EVP_CIPHER *cipher, uint32_t iterations, |
134 | | const char *pass, size_t pass_len, |
135 | 0 | const uint8_t *salt, size_t salt_len) { |
136 | 0 | int cipher_nid = EVP_CIPHER_nid(cipher); |
137 | 0 | if (cipher_nid == NID_undef) { |
138 | 0 | OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); |
139 | 0 | return 0; |
140 | 0 | } |
141 | | |
142 | | // Generate a random IV. |
143 | 0 | uint8_t iv[EVP_MAX_IV_LENGTH]; |
144 | 0 | if (!RAND_bytes(iv, EVP_CIPHER_iv_length(cipher))) { |
145 | 0 | return 0; |
146 | 0 | } |
147 | | |
148 | | // See RFC 8018, appendix A. |
149 | 0 | CBB algorithm, param, kdf, kdf_param, prf, cipher_cbb; |
150 | 0 | if (!CBB_add_asn1(out, &algorithm, CBS_ASN1_SEQUENCE) || |
151 | 0 | !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, kPBES2, |
152 | 0 | sizeof(kPBES2)) || |
153 | 0 | !CBB_add_asn1(&algorithm, ¶m, CBS_ASN1_SEQUENCE) || |
154 | 0 | !CBB_add_asn1(¶m, &kdf, CBS_ASN1_SEQUENCE) || |
155 | 0 | !CBB_add_asn1_element(&kdf, CBS_ASN1_OBJECT, kPBKDF2, sizeof(kPBKDF2)) || |
156 | 0 | !CBB_add_asn1(&kdf, &kdf_param, CBS_ASN1_SEQUENCE) || |
157 | 0 | !CBB_add_asn1_octet_string(&kdf_param, salt, salt_len) || |
158 | 0 | !CBB_add_asn1_uint64(&kdf_param, iterations) || |
159 | | // Specify a key length for RC2. |
160 | 0 | (cipher_nid == NID_rc2_cbc && |
161 | 0 | !CBB_add_asn1_uint64(&kdf_param, EVP_CIPHER_key_length(cipher))) || |
162 | | // Use hmacWithSHA256 for the PRF. |
163 | 0 | !CBB_add_asn1(&kdf_param, &prf, CBS_ASN1_SEQUENCE) || |
164 | 0 | !CBB_add_asn1_element(&prf, CBS_ASN1_OBJECT, kHMACWithSHA256, |
165 | 0 | sizeof(kHMACWithSHA256)) || |
166 | 0 | !CBB_add_asn1_element(&prf, CBS_ASN1_NULL, nullptr, 0) || |
167 | 0 | !CBB_add_asn1(¶m, &cipher_cbb, CBS_ASN1_SEQUENCE) || |
168 | 0 | !add_cipher_oid(&cipher_cbb, cipher_nid) || |
169 | | // RFC 8018 says RC2-CBC and RC5-CBC-Pad use a SEQUENCE with version and |
170 | | // IV, but OpenSSL always uses an OCTET STRING IV, so we do the same. |
171 | 0 | !CBB_add_asn1_octet_string(&cipher_cbb, iv, |
172 | 0 | EVP_CIPHER_iv_length(cipher)) || |
173 | 0 | !CBB_flush(out)) { |
174 | 0 | return 0; |
175 | 0 | } |
176 | | |
177 | 0 | return pkcs5_pbe2_cipher_init(ctx, cipher, EVP_sha256(), iterations, pass, |
178 | 0 | pass_len, salt, salt_len, iv, |
179 | 0 | EVP_CIPHER_iv_length(cipher), 1 /* encrypt */); |
180 | 0 | } |
181 | | |
182 | | int bssl::PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, |
183 | | EVP_CIPHER_CTX *ctx, const char *pass, |
184 | 2 | size_t pass_len, CBS *param) { |
185 | 2 | CBS pbe_param, kdf, kdf_obj, enc_scheme, enc_obj; |
186 | 2 | if (!CBS_get_asn1(param, &pbe_param, CBS_ASN1_SEQUENCE) || |
187 | 2 | CBS_len(param) != 0 || |
188 | 2 | !CBS_get_asn1(&pbe_param, &kdf, CBS_ASN1_SEQUENCE) || |
189 | 2 | !CBS_get_asn1(&pbe_param, &enc_scheme, CBS_ASN1_SEQUENCE) || |
190 | 2 | CBS_len(&pbe_param) != 0 || |
191 | 2 | !CBS_get_asn1(&kdf, &kdf_obj, CBS_ASN1_OBJECT) || |
192 | 2 | !CBS_get_asn1(&enc_scheme, &enc_obj, CBS_ASN1_OBJECT)) { |
193 | 0 | OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); |
194 | 0 | return 0; |
195 | 0 | } |
196 | | |
197 | | // Only PBKDF2 is supported. |
198 | 2 | if (!CBS_mem_equal(&kdf_obj, kPBKDF2, sizeof(kPBKDF2))) { |
199 | 0 | OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION); |
200 | 0 | return 0; |
201 | 0 | } |
202 | | |
203 | | // See if we recognise the encryption algorithm. |
204 | 2 | const EVP_CIPHER *cipher = cbs_to_cipher(&enc_obj); |
205 | 2 | if (cipher == nullptr) { |
206 | 0 | OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_CIPHER); |
207 | 0 | return 0; |
208 | 0 | } |
209 | | |
210 | | // Parse the KDF parameters. See RFC 8018, appendix A.2. |
211 | 2 | CBS pbkdf2_params, salt; |
212 | 2 | uint64_t iterations; |
213 | 2 | if (!CBS_get_asn1(&kdf, &pbkdf2_params, CBS_ASN1_SEQUENCE) || |
214 | 2 | CBS_len(&kdf) != 0 || |
215 | 2 | !CBS_get_asn1(&pbkdf2_params, &salt, CBS_ASN1_OCTETSTRING) || |
216 | 2 | !CBS_get_asn1_uint64(&pbkdf2_params, &iterations)) { |
217 | 0 | OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); |
218 | 0 | return 0; |
219 | 0 | } |
220 | | |
221 | 2 | if (!pkcs12_iterations_acceptable(iterations)) { |
222 | 0 | OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT); |
223 | 0 | return 0; |
224 | 0 | } |
225 | | |
226 | | // The optional keyLength parameter, if present, must match the key length of |
227 | | // the cipher. |
228 | 2 | if (CBS_peek_asn1_tag(&pbkdf2_params, CBS_ASN1_INTEGER)) { |
229 | 0 | uint64_t key_len; |
230 | 0 | if (!CBS_get_asn1_uint64(&pbkdf2_params, &key_len)) { |
231 | 0 | OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); |
232 | 0 | return 0; |
233 | 0 | } |
234 | | |
235 | 0 | if (key_len != EVP_CIPHER_key_length(cipher)) { |
236 | 0 | OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_KEYLENGTH); |
237 | 0 | return 0; |
238 | 0 | } |
239 | 0 | } |
240 | | |
241 | 2 | const EVP_MD *md = EVP_sha1(); |
242 | 2 | if (CBS_len(&pbkdf2_params) != 0) { |
243 | 0 | CBS alg_id, prf; |
244 | 0 | if (!CBS_get_asn1(&pbkdf2_params, &alg_id, CBS_ASN1_SEQUENCE) || |
245 | 0 | !CBS_get_asn1(&alg_id, &prf, CBS_ASN1_OBJECT) || |
246 | 0 | CBS_len(&pbkdf2_params) != 0) { |
247 | 0 | OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); |
248 | 0 | return 0; |
249 | 0 | } |
250 | | |
251 | 0 | if (CBS_mem_equal(&prf, kHMACWithSHA1, sizeof(kHMACWithSHA1))) { |
252 | | // hmacWithSHA1 is the DEFAULT, so DER requires it be omitted, but we |
253 | | // match OpenSSL in tolerating it being present. |
254 | 0 | md = EVP_sha1(); |
255 | 0 | } else if (CBS_mem_equal(&prf, kHMACWithSHA256, sizeof(kHMACWithSHA256))) { |
256 | 0 | md = EVP_sha256(); |
257 | 0 | } else { |
258 | 0 | OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRF); |
259 | 0 | return 0; |
260 | 0 | } |
261 | | |
262 | | // All supported PRFs use a NULL parameter. |
263 | 0 | CBS null; |
264 | 0 | if (!CBS_get_asn1(&alg_id, &null, CBS_ASN1_NULL) || |
265 | 0 | CBS_len(&null) != 0 || |
266 | 0 | CBS_len(&alg_id) != 0) { |
267 | 0 | OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR); |
268 | 0 | return 0; |
269 | 0 | } |
270 | 0 | } |
271 | | |
272 | | // Parse the encryption scheme parameters. Note OpenSSL does not match the |
273 | | // specification. Per RFC 8018, this should depend on the encryption scheme. |
274 | | // In particular, RC2-CBC uses a SEQUENCE with version and IV. We align with |
275 | | // OpenSSL. |
276 | 2 | CBS iv; |
277 | 2 | if (!CBS_get_asn1(&enc_scheme, &iv, CBS_ASN1_OCTETSTRING) || |
278 | 2 | CBS_len(&enc_scheme) != 0) { |
279 | 0 | OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRF); |
280 | 0 | return 0; |
281 | 0 | } |
282 | | |
283 | 2 | return pkcs5_pbe2_cipher_init(ctx, cipher, md, (uint32_t)iterations, pass, |
284 | 2 | pass_len, CBS_data(&salt), CBS_len(&salt), |
285 | 2 | CBS_data(&iv), CBS_len(&iv), 0 /* decrypt */); |
286 | 2 | } |