2014-06-20 20:00:00 +01:00
|
|
|
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
|
|
|
* project 1999-2004.
|
|
|
|
*/
|
|
|
|
/* ====================================================================
|
|
|
|
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
*
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
*
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
|
|
|
*
|
|
|
|
* 3. All advertising materials mentioning features or use of this
|
|
|
|
* software must display the following acknowledgment:
|
|
|
|
* "This product includes software developed by the OpenSSL Project
|
|
|
|
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
|
|
|
*
|
|
|
|
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
|
|
|
* endorse or promote products derived from this software without
|
|
|
|
* prior written permission. For written permission, please contact
|
|
|
|
* licensing@OpenSSL.org.
|
|
|
|
*
|
|
|
|
* 5. Products derived from this software may not be called "OpenSSL"
|
|
|
|
* nor may "OpenSSL" appear in their names without prior written
|
|
|
|
* permission of the OpenSSL Project.
|
|
|
|
*
|
|
|
|
* 6. Redistributions of any form whatsoever must retain the following
|
|
|
|
* acknowledgment:
|
|
|
|
* "This product includes software developed by the OpenSSL Project
|
|
|
|
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
|
|
|
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
|
|
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
|
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
* ====================================================================
|
|
|
|
*
|
|
|
|
* This product includes cryptographic software written by Eric Young
|
|
|
|
* (eay@cryptsoft.com). This product includes software written by Tim
|
|
|
|
* Hudson (tjh@cryptsoft.com). */
|
|
|
|
|
2016-12-29 03:06:11 +00:00
|
|
|
#include <openssl/pkcs8.h>
|
|
|
|
|
2015-08-21 19:09:44 +01:00
|
|
|
#include <limits.h>
|
2015-01-31 01:08:37 +00:00
|
|
|
#include <string.h>
|
2014-06-20 20:00:00 +01:00
|
|
|
|
2016-12-28 22:21:10 +00:00
|
|
|
#include <openssl/bytestring.h>
|
2014-06-20 20:00:00 +01:00
|
|
|
#include <openssl/cipher.h>
|
|
|
|
#include <openssl/err.h>
|
|
|
|
#include <openssl/mem.h>
|
2017-03-14 05:12:02 +00:00
|
|
|
#include <openssl/nid.h>
|
2014-06-20 20:00:00 +01:00
|
|
|
#include <openssl/rand.h>
|
|
|
|
|
|
|
|
#include "internal.h"
|
2016-12-13 06:07:13 +00:00
|
|
|
#include "../internal.h"
|
2014-06-20 20:00:00 +01:00
|
|
|
|
|
|
|
|
2017-03-14 04:13:00 +00:00
|
|
|
/* 1.2.840.113549.1.5.12 */
|
|
|
|
static const uint8_t kPBKDF2[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
|
|
|
|
0x0d, 0x01, 0x05, 0x0c};
|
|
|
|
|
|
|
|
/* 1.2.840.113549.1.5.13 */
|
|
|
|
static const uint8_t kPBES2[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
|
|
|
|
0x0d, 0x01, 0x05, 0x0d};
|
|
|
|
|
|
|
|
/* 1.2.840.113549.2.7 */
|
|
|
|
static const uint8_t kHMACWithSHA1[] = {0x2a, 0x86, 0x48, 0x86,
|
|
|
|
0xf7, 0x0d, 0x02, 0x07};
|
|
|
|
|
2017-03-14 05:12:02 +00:00
|
|
|
static const struct {
|
|
|
|
uint8_t oid[9];
|
|
|
|
uint8_t oid_len;
|
|
|
|
int nid;
|
|
|
|
const EVP_CIPHER *(*cipher_func)(void);
|
|
|
|
} kCipherOIDs[] = {
|
|
|
|
/* 1.2.840.113549.3.2 */
|
|
|
|
{{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x02},
|
|
|
|
8,
|
|
|
|
NID_rc2_cbc,
|
|
|
|
&EVP_rc2_cbc},
|
|
|
|
/* 1.2.840.113549.3.7 */
|
|
|
|
{{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07},
|
|
|
|
8,
|
|
|
|
NID_des_ede3_cbc,
|
|
|
|
&EVP_des_ede3_cbc},
|
|
|
|
/* 2.16.840.1.101.3.4.1.2 */
|
|
|
|
{{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02},
|
|
|
|
9,
|
|
|
|
NID_aes_128_cbc,
|
|
|
|
&EVP_aes_128_cbc},
|
|
|
|
/* 2.16.840.1.101.3.4.1.22 */
|
|
|
|
{{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x16},
|
|
|
|
9,
|
|
|
|
NID_aes_192_cbc,
|
|
|
|
&EVP_aes_192_cbc},
|
|
|
|
/* 2.16.840.1.101.3.4.1.42 */
|
|
|
|
{{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2a},
|
|
|
|
9,
|
|
|
|
NID_aes_256_cbc,
|
|
|
|
&EVP_aes_256_cbc},
|
|
|
|
};
|
|
|
|
|
|
|
|
static const EVP_CIPHER *cbs_to_cipher(const CBS *cbs) {
|
|
|
|
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kCipherOIDs); i++) {
|
|
|
|
if (CBS_mem_equal(cbs, kCipherOIDs[i].oid, kCipherOIDs[i].oid_len)) {
|
|
|
|
return kCipherOIDs[i].cipher_func();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int add_cipher_oid(CBB *out, int nid) {
|
|
|
|
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kCipherOIDs); i++) {
|
|
|
|
if (kCipherOIDs[i].nid == nid) {
|
|
|
|
CBB child;
|
|
|
|
return CBB_add_asn1(out, &child, CBS_ASN1_OBJECT) &&
|
|
|
|
CBB_add_bytes(&child, kCipherOIDs[i].oid,
|
|
|
|
kCipherOIDs[i].oid_len) &&
|
|
|
|
CBB_flush(out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_CIPHER);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-12-30 07:17:24 +00:00
|
|
|
static int pkcs5_pbe2_cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
Push password encoding back into pkcs12_key_gen.
With PKCS8_encrypt_pbe and PKCS8_decrypt_pbe gone in
3e8b782c0cc0d9621f622cf80ab1a9bcf442fa17, we can restore the old
arrangement where the password encoding was handled in pkcs12_key_gen.
This simplifies the interface for the follow-up crypto/asn1 split.
Note this change is *not* a no-op for PKCS#12 files which use PBES2.
Before, we would perform the PKCS#12 password encoding for all parts of
PKCS#12 processing. The new behavior is we only perform it for the parts
that go through the PKCS#12 KDF. For such a file, it would only be the
MAC.
I believe the specification supports our new behavior. Although RFC 7292
B.1 says something which implies that the transformation is about
converting passwords to byte strings and would thus be universal,
appendix B itself is prefaced with:
Note that this method for password privacy mode is not recommended
and is deprecated for new usage. The procedures and algorithms
defined in PKCS #5 v2.1 [13] [22] should be used instead.
Specifically, PBES2 should be used as encryption scheme, with PBKDF2
as the key derivation function.
"This method" refers to the key derivation and not the password
formatting, but it does give support to the theory that password
formatting is tied to PKCS#12 key derivation.
(Of course, if one believes PKCS#12's assertion that their inane
encoding (NUL-terminated UTF-16!) is because PKCS#5 failed to talk about
passwords as Unicode strings, one would think that PBES2 (also in
PKCS#5) would have the same issue and thus need PKCS#12 to valiantly
save the day with an encoding...)
This matches OpenSSL's behavior and that of recent versions of NSS. See
https://bugzilla.mozilla.org/show_bug.cgi?id=1268141. I was unable to
figure out what variants, if any, macOS accepts.
BUG=54
Change-Id: I9a1bb4d5e168e6e76b82241e4634b1103e620b9b
Reviewed-on: https://boringssl-review.googlesource.com/14213
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-14 05:43:23 +00:00
|
|
|
unsigned iterations, const char *pass,
|
|
|
|
size_t pass_len, const uint8_t *salt,
|
2016-12-30 07:17:24 +00:00
|
|
|
size_t salt_len, const uint8_t *iv,
|
|
|
|
size_t iv_len, int enc) {
|
|
|
|
if (iv_len != EVP_CIPHER_iv_length(cipher)) {
|
|
|
|
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t key[EVP_MAX_KEY_LENGTH];
|
Push password encoding back into pkcs12_key_gen.
With PKCS8_encrypt_pbe and PKCS8_decrypt_pbe gone in
3e8b782c0cc0d9621f622cf80ab1a9bcf442fa17, we can restore the old
arrangement where the password encoding was handled in pkcs12_key_gen.
This simplifies the interface for the follow-up crypto/asn1 split.
Note this change is *not* a no-op for PKCS#12 files which use PBES2.
Before, we would perform the PKCS#12 password encoding for all parts of
PKCS#12 processing. The new behavior is we only perform it for the parts
that go through the PKCS#12 KDF. For such a file, it would only be the
MAC.
I believe the specification supports our new behavior. Although RFC 7292
B.1 says something which implies that the transformation is about
converting passwords to byte strings and would thus be universal,
appendix B itself is prefaced with:
Note that this method for password privacy mode is not recommended
and is deprecated for new usage. The procedures and algorithms
defined in PKCS #5 v2.1 [13] [22] should be used instead.
Specifically, PBES2 should be used as encryption scheme, with PBKDF2
as the key derivation function.
"This method" refers to the key derivation and not the password
formatting, but it does give support to the theory that password
formatting is tied to PKCS#12 key derivation.
(Of course, if one believes PKCS#12's assertion that their inane
encoding (NUL-terminated UTF-16!) is because PKCS#5 failed to talk about
passwords as Unicode strings, one would think that PBES2 (also in
PKCS#5) would have the same issue and thus need PKCS#12 to valiantly
save the day with an encoding...)
This matches OpenSSL's behavior and that of recent versions of NSS. See
https://bugzilla.mozilla.org/show_bug.cgi?id=1268141. I was unable to
figure out what variants, if any, macOS accepts.
BUG=54
Change-Id: I9a1bb4d5e168e6e76b82241e4634b1103e620b9b
Reviewed-on: https://boringssl-review.googlesource.com/14213
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-14 05:43:23 +00:00
|
|
|
int ret = PKCS5_PBKDF2_HMAC_SHA1(pass, pass_len, salt, salt_len, iterations,
|
2016-12-30 07:17:24 +00:00
|
|
|
EVP_CIPHER_key_length(cipher), key) &&
|
|
|
|
EVP_CipherInit_ex(ctx, cipher, NULL /* engine */, key, iv, enc);
|
|
|
|
OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int PKCS5_pbe2_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx,
|
|
|
|
const EVP_CIPHER *cipher, unsigned iterations,
|
Push password encoding back into pkcs12_key_gen.
With PKCS8_encrypt_pbe and PKCS8_decrypt_pbe gone in
3e8b782c0cc0d9621f622cf80ab1a9bcf442fa17, we can restore the old
arrangement where the password encoding was handled in pkcs12_key_gen.
This simplifies the interface for the follow-up crypto/asn1 split.
Note this change is *not* a no-op for PKCS#12 files which use PBES2.
Before, we would perform the PKCS#12 password encoding for all parts of
PKCS#12 processing. The new behavior is we only perform it for the parts
that go through the PKCS#12 KDF. For such a file, it would only be the
MAC.
I believe the specification supports our new behavior. Although RFC 7292
B.1 says something which implies that the transformation is about
converting passwords to byte strings and would thus be universal,
appendix B itself is prefaced with:
Note that this method for password privacy mode is not recommended
and is deprecated for new usage. The procedures and algorithms
defined in PKCS #5 v2.1 [13] [22] should be used instead.
Specifically, PBES2 should be used as encryption scheme, with PBKDF2
as the key derivation function.
"This method" refers to the key derivation and not the password
formatting, but it does give support to the theory that password
formatting is tied to PKCS#12 key derivation.
(Of course, if one believes PKCS#12's assertion that their inane
encoding (NUL-terminated UTF-16!) is because PKCS#5 failed to talk about
passwords as Unicode strings, one would think that PBES2 (also in
PKCS#5) would have the same issue and thus need PKCS#12 to valiantly
save the day with an encoding...)
This matches OpenSSL's behavior and that of recent versions of NSS. See
https://bugzilla.mozilla.org/show_bug.cgi?id=1268141. I was unable to
figure out what variants, if any, macOS accepts.
BUG=54
Change-Id: I9a1bb4d5e168e6e76b82241e4634b1103e620b9b
Reviewed-on: https://boringssl-review.googlesource.com/14213
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-14 05:43:23 +00:00
|
|
|
const char *pass, size_t pass_len,
|
2016-12-30 07:17:24 +00:00
|
|
|
const uint8_t *salt, size_t salt_len) {
|
2016-12-28 22:21:10 +00:00
|
|
|
int cipher_nid = EVP_CIPHER_nid(cipher);
|
|
|
|
if (cipher_nid == NID_undef) {
|
|
|
|
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
|
2016-12-30 07:17:24 +00:00
|
|
|
return 0;
|
2016-12-28 22:21:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Generate a random IV. */
|
|
|
|
uint8_t iv[EVP_MAX_IV_LENGTH];
|
|
|
|
if (!RAND_bytes(iv, EVP_CIPHER_iv_length(cipher))) {
|
2016-12-30 07:17:24 +00:00
|
|
|
return 0;
|
2016-12-28 22:21:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* See RFC 2898, appendix A. */
|
2017-03-14 04:13:00 +00:00
|
|
|
CBB algorithm, oid, param, kdf, kdf_oid, kdf_param, salt_cbb, cipher_cbb,
|
|
|
|
iv_cbb;
|
2016-12-30 07:17:24 +00:00
|
|
|
if (!CBB_add_asn1(out, &algorithm, CBS_ASN1_SEQUENCE) ||
|
2017-03-14 04:13:00 +00:00
|
|
|
!CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
|
|
|
|
!CBB_add_bytes(&oid, kPBES2, sizeof(kPBES2)) ||
|
2016-12-28 22:21:10 +00:00
|
|
|
!CBB_add_asn1(&algorithm, ¶m, CBS_ASN1_SEQUENCE) ||
|
|
|
|
!CBB_add_asn1(¶m, &kdf, CBS_ASN1_SEQUENCE) ||
|
2017-03-14 04:13:00 +00:00
|
|
|
!CBB_add_asn1(&kdf, &kdf_oid, CBS_ASN1_OBJECT) ||
|
|
|
|
!CBB_add_bytes(&kdf_oid, kPBKDF2, sizeof(kPBKDF2)) ||
|
2016-12-28 22:21:10 +00:00
|
|
|
!CBB_add_asn1(&kdf, &kdf_param, CBS_ASN1_SEQUENCE) ||
|
|
|
|
!CBB_add_asn1(&kdf_param, &salt_cbb, CBS_ASN1_OCTETSTRING) ||
|
|
|
|
!CBB_add_bytes(&salt_cbb, salt, salt_len) ||
|
2016-12-30 07:17:24 +00:00
|
|
|
!CBB_add_asn1_uint64(&kdf_param, iterations) ||
|
2016-12-28 22:21:10 +00:00
|
|
|
/* Specify a key length for RC2. */
|
|
|
|
(cipher_nid == NID_rc2_cbc &&
|
|
|
|
!CBB_add_asn1_uint64(&kdf_param, EVP_CIPHER_key_length(cipher))) ||
|
|
|
|
/* Omit the PRF. We use the default hmacWithSHA1. */
|
|
|
|
!CBB_add_asn1(¶m, &cipher_cbb, CBS_ASN1_SEQUENCE) ||
|
2017-03-14 05:12:02 +00:00
|
|
|
!add_cipher_oid(&cipher_cbb, cipher_nid) ||
|
2016-12-28 22:21:10 +00:00
|
|
|
/* RFC 2898 says RC2-CBC and RC5-CBC-Pad use a SEQUENCE with version and
|
|
|
|
* IV, but OpenSSL always uses an OCTET STRING IV, so we do the same. */
|
|
|
|
!CBB_add_asn1(&cipher_cbb, &iv_cbb, CBS_ASN1_OCTETSTRING) ||
|
|
|
|
!CBB_add_bytes(&iv_cbb, iv, EVP_CIPHER_iv_length(cipher)) ||
|
2016-12-30 07:17:24 +00:00
|
|
|
!CBB_flush(out)) {
|
|
|
|
return 0;
|
2016-12-28 22:21:10 +00:00
|
|
|
}
|
|
|
|
|
Push password encoding back into pkcs12_key_gen.
With PKCS8_encrypt_pbe and PKCS8_decrypt_pbe gone in
3e8b782c0cc0d9621f622cf80ab1a9bcf442fa17, we can restore the old
arrangement where the password encoding was handled in pkcs12_key_gen.
This simplifies the interface for the follow-up crypto/asn1 split.
Note this change is *not* a no-op for PKCS#12 files which use PBES2.
Before, we would perform the PKCS#12 password encoding for all parts of
PKCS#12 processing. The new behavior is we only perform it for the parts
that go through the PKCS#12 KDF. For such a file, it would only be the
MAC.
I believe the specification supports our new behavior. Although RFC 7292
B.1 says something which implies that the transformation is about
converting passwords to byte strings and would thus be universal,
appendix B itself is prefaced with:
Note that this method for password privacy mode is not recommended
and is deprecated for new usage. The procedures and algorithms
defined in PKCS #5 v2.1 [13] [22] should be used instead.
Specifically, PBES2 should be used as encryption scheme, with PBKDF2
as the key derivation function.
"This method" refers to the key derivation and not the password
formatting, but it does give support to the theory that password
formatting is tied to PKCS#12 key derivation.
(Of course, if one believes PKCS#12's assertion that their inane
encoding (NUL-terminated UTF-16!) is because PKCS#5 failed to talk about
passwords as Unicode strings, one would think that PBES2 (also in
PKCS#5) would have the same issue and thus need PKCS#12 to valiantly
save the day with an encoding...)
This matches OpenSSL's behavior and that of recent versions of NSS. See
https://bugzilla.mozilla.org/show_bug.cgi?id=1268141. I was unable to
figure out what variants, if any, macOS accepts.
BUG=54
Change-Id: I9a1bb4d5e168e6e76b82241e4634b1103e620b9b
Reviewed-on: https://boringssl-review.googlesource.com/14213
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-14 05:43:23 +00:00
|
|
|
return pkcs5_pbe2_cipher_init(ctx, cipher, iterations, pass, pass_len, salt,
|
|
|
|
salt_len, iv, EVP_CIPHER_iv_length(cipher),
|
|
|
|
1 /* encrypt */);
|
2014-06-20 20:00:00 +01:00
|
|
|
}
|
|
|
|
|
2016-12-30 07:17:24 +00:00
|
|
|
int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
|
Push password encoding back into pkcs12_key_gen.
With PKCS8_encrypt_pbe and PKCS8_decrypt_pbe gone in
3e8b782c0cc0d9621f622cf80ab1a9bcf442fa17, we can restore the old
arrangement where the password encoding was handled in pkcs12_key_gen.
This simplifies the interface for the follow-up crypto/asn1 split.
Note this change is *not* a no-op for PKCS#12 files which use PBES2.
Before, we would perform the PKCS#12 password encoding for all parts of
PKCS#12 processing. The new behavior is we only perform it for the parts
that go through the PKCS#12 KDF. For such a file, it would only be the
MAC.
I believe the specification supports our new behavior. Although RFC 7292
B.1 says something which implies that the transformation is about
converting passwords to byte strings and would thus be universal,
appendix B itself is prefaced with:
Note that this method for password privacy mode is not recommended
and is deprecated for new usage. The procedures and algorithms
defined in PKCS #5 v2.1 [13] [22] should be used instead.
Specifically, PBES2 should be used as encryption scheme, with PBKDF2
as the key derivation function.
"This method" refers to the key derivation and not the password
formatting, but it does give support to the theory that password
formatting is tied to PKCS#12 key derivation.
(Of course, if one believes PKCS#12's assertion that their inane
encoding (NUL-terminated UTF-16!) is because PKCS#5 failed to talk about
passwords as Unicode strings, one would think that PBES2 (also in
PKCS#5) would have the same issue and thus need PKCS#12 to valiantly
save the day with an encoding...)
This matches OpenSSL's behavior and that of recent versions of NSS. See
https://bugzilla.mozilla.org/show_bug.cgi?id=1268141. I was unable to
figure out what variants, if any, macOS accepts.
BUG=54
Change-Id: I9a1bb4d5e168e6e76b82241e4634b1103e620b9b
Reviewed-on: https://boringssl-review.googlesource.com/14213
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-14 05:43:23 +00:00
|
|
|
const char *pass, size_t pass_len, CBS *param) {
|
2016-12-30 07:17:24 +00:00
|
|
|
CBS pbe_param, kdf, kdf_obj, enc_scheme, enc_obj;
|
|
|
|
if (!CBS_get_asn1(param, &pbe_param, CBS_ASN1_SEQUENCE) ||
|
|
|
|
CBS_len(param) != 0 ||
|
2016-12-29 03:06:11 +00:00
|
|
|
!CBS_get_asn1(&pbe_param, &kdf, CBS_ASN1_SEQUENCE) ||
|
|
|
|
!CBS_get_asn1(&pbe_param, &enc_scheme, CBS_ASN1_SEQUENCE) ||
|
|
|
|
CBS_len(&pbe_param) != 0 ||
|
|
|
|
!CBS_get_asn1(&kdf, &kdf_obj, CBS_ASN1_OBJECT) ||
|
|
|
|
!CBS_get_asn1(&enc_scheme, &enc_obj, CBS_ASN1_OBJECT)) {
|
2015-08-21 19:09:44 +01:00
|
|
|
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
|
2016-12-29 03:06:11 +00:00
|
|
|
return 0;
|
2015-08-21 19:09:44 +01:00
|
|
|
}
|
|
|
|
|
2017-03-14 04:13:00 +00:00
|
|
|
/* Only PBKDF2 is supported. */
|
|
|
|
if (!CBS_mem_equal(&kdf_obj, kPBKDF2, sizeof(kPBKDF2))) {
|
2016-12-29 03:06:11 +00:00
|
|
|
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION);
|
|
|
|
return 0;
|
2015-08-21 19:09:44 +01:00
|
|
|
}
|
|
|
|
|
2016-12-29 03:06:11 +00:00
|
|
|
/* See if we recognise the encryption algorithm. */
|
2017-03-14 05:12:02 +00:00
|
|
|
const EVP_CIPHER *cipher = cbs_to_cipher(&enc_obj);
|
2016-12-29 03:06:11 +00:00
|
|
|
if (cipher == NULL) {
|
|
|
|
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_CIPHER);
|
|
|
|
return 0;
|
2015-08-21 19:09:44 +01:00
|
|
|
}
|
|
|
|
|
2017-03-22 22:44:46 +00:00
|
|
|
/* Parse the KDF parameters. See RFC 8018, appendix A.2. */
|
2016-12-29 03:06:11 +00:00
|
|
|
CBS pbkdf2_params, salt;
|
|
|
|
uint64_t iterations;
|
|
|
|
if (!CBS_get_asn1(&kdf, &pbkdf2_params, CBS_ASN1_SEQUENCE) ||
|
|
|
|
CBS_len(&kdf) != 0 ||
|
|
|
|
!CBS_get_asn1(&pbkdf2_params, &salt, CBS_ASN1_OCTETSTRING) ||
|
|
|
|
!CBS_get_asn1_uint64(&pbkdf2_params, &iterations)) {
|
|
|
|
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
|
|
|
|
return 0;
|
2015-08-21 19:09:44 +01:00
|
|
|
}
|
|
|
|
|
2016-12-29 03:06:11 +00:00
|
|
|
if (iterations == 0 || iterations > UINT_MAX) {
|
2015-08-21 19:09:44 +01:00
|
|
|
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT);
|
2016-12-29 03:06:11 +00:00
|
|
|
return 0;
|
2015-08-21 19:09:44 +01:00
|
|
|
}
|
|
|
|
|
2016-12-29 03:06:11 +00:00
|
|
|
/* The optional keyLength parameter, if present, must match the key length of
|
|
|
|
* the cipher. */
|
|
|
|
if (CBS_peek_asn1_tag(&pbkdf2_params, CBS_ASN1_INTEGER)) {
|
|
|
|
uint64_t key_len;
|
|
|
|
if (!CBS_get_asn1_uint64(&pbkdf2_params, &key_len)) {
|
|
|
|
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
|
|
|
|
return 0;
|
|
|
|
}
|
2015-08-21 19:09:44 +01:00
|
|
|
|
2016-12-29 03:06:11 +00:00
|
|
|
if (key_len != EVP_CIPHER_key_length(cipher)) {
|
|
|
|
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_KEYLENGTH);
|
|
|
|
return 0;
|
|
|
|
}
|
2015-08-21 19:09:44 +01:00
|
|
|
}
|
|
|
|
|
2016-12-29 03:06:11 +00:00
|
|
|
if (CBS_len(&pbkdf2_params) != 0) {
|
2017-03-22 22:44:46 +00:00
|
|
|
CBS alg_id, prf;
|
|
|
|
if (!CBS_get_asn1(&pbkdf2_params, &alg_id, CBS_ASN1_SEQUENCE) ||
|
|
|
|
!CBS_get_asn1(&alg_id, &prf, CBS_ASN1_OBJECT) ||
|
2016-12-29 03:06:11 +00:00
|
|
|
CBS_len(&pbkdf2_params) != 0) {
|
|
|
|
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
|
|
|
|
return 0;
|
|
|
|
}
|
2015-08-21 19:09:44 +01:00
|
|
|
|
2016-12-29 03:06:11 +00:00
|
|
|
/* We only support hmacWithSHA1. It is the DEFAULT, so DER requires it be
|
|
|
|
* omitted, but we match OpenSSL in tolerating it being present. */
|
2017-03-14 04:13:00 +00:00
|
|
|
if (!CBS_mem_equal(&prf, kHMACWithSHA1, sizeof(kHMACWithSHA1))) {
|
2016-12-29 03:06:11 +00:00
|
|
|
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRF);
|
|
|
|
return 0;
|
|
|
|
}
|
2017-03-22 22:44:46 +00:00
|
|
|
|
|
|
|
/* hmacWithSHA1 has a NULL parameter. */
|
|
|
|
CBS null;
|
|
|
|
if (!CBS_get_asn1(&alg_id, &null, CBS_ASN1_NULL) ||
|
|
|
|
CBS_len(&null) != 0 ||
|
|
|
|
CBS_len(&alg_id) != 0) {
|
|
|
|
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
|
|
|
|
return 0;
|
|
|
|
}
|
2015-08-21 19:09:44 +01:00
|
|
|
}
|
|
|
|
|
2016-12-29 03:06:11 +00:00
|
|
|
/* Parse the encryption scheme parameters. Note OpenSSL does not match the
|
|
|
|
* specification. Per RFC 2898, this should depend on the encryption scheme.
|
2017-03-14 05:12:02 +00:00
|
|
|
* In particular, RC2-CBC uses a SEQUENCE with version and IV. We align with
|
|
|
|
* OpenSSL. */
|
2016-12-29 03:06:11 +00:00
|
|
|
CBS iv;
|
|
|
|
if (!CBS_get_asn1(&enc_scheme, &iv, CBS_ASN1_OCTETSTRING) ||
|
|
|
|
CBS_len(&enc_scheme) != 0) {
|
|
|
|
OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRF);
|
|
|
|
return 0;
|
2015-08-21 19:09:44 +01:00
|
|
|
}
|
|
|
|
|
Push password encoding back into pkcs12_key_gen.
With PKCS8_encrypt_pbe and PKCS8_decrypt_pbe gone in
3e8b782c0cc0d9621f622cf80ab1a9bcf442fa17, we can restore the old
arrangement where the password encoding was handled in pkcs12_key_gen.
This simplifies the interface for the follow-up crypto/asn1 split.
Note this change is *not* a no-op for PKCS#12 files which use PBES2.
Before, we would perform the PKCS#12 password encoding for all parts of
PKCS#12 processing. The new behavior is we only perform it for the parts
that go through the PKCS#12 KDF. For such a file, it would only be the
MAC.
I believe the specification supports our new behavior. Although RFC 7292
B.1 says something which implies that the transformation is about
converting passwords to byte strings and would thus be universal,
appendix B itself is prefaced with:
Note that this method for password privacy mode is not recommended
and is deprecated for new usage. The procedures and algorithms
defined in PKCS #5 v2.1 [13] [22] should be used instead.
Specifically, PBES2 should be used as encryption scheme, with PBKDF2
as the key derivation function.
"This method" refers to the key derivation and not the password
formatting, but it does give support to the theory that password
formatting is tied to PKCS#12 key derivation.
(Of course, if one believes PKCS#12's assertion that their inane
encoding (NUL-terminated UTF-16!) is because PKCS#5 failed to talk about
passwords as Unicode strings, one would think that PBES2 (also in
PKCS#5) would have the same issue and thus need PKCS#12 to valiantly
save the day with an encoding...)
This matches OpenSSL's behavior and that of recent versions of NSS. See
https://bugzilla.mozilla.org/show_bug.cgi?id=1268141. I was unable to
figure out what variants, if any, macOS accepts.
BUG=54
Change-Id: I9a1bb4d5e168e6e76b82241e4634b1103e620b9b
Reviewed-on: https://boringssl-review.googlesource.com/14213
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-03-14 05:43:23 +00:00
|
|
|
return pkcs5_pbe2_cipher_init(ctx, cipher, (unsigned)iterations, pass,
|
|
|
|
pass_len, CBS_data(&salt), CBS_len(&salt),
|
2016-12-30 07:17:24 +00:00
|
|
|
CBS_data(&iv), CBS_len(&iv), 0 /* decrypt */);
|
2015-08-21 19:09:44 +01:00
|
|
|
}
|