Coverage Report

Created: 2026-02-16 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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, &param, CBS_ASN1_SEQUENCE) ||
154
0
      !CBB_add_asn1(&param, &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(&param, &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
}