From 915990e450e769e370fcacbfd8ed58ab6afaf2bf Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 21 Aug 2023 15:47:55 +0200 Subject: [PATCH 39/48] 0084-pbkdf2-Set-minimum-password-length-of-8-bytes.patch Patch-name: 0084-pbkdf2-Set-minimum-password-length-of-8-bytes.patch Patch-id: 84 --- providers/implementations/kdfs/pbkdf2.c | 27 ++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) Index: openssl-3.5.0-beta1/providers/implementations/kdfs/pbkdf2.c =================================================================== --- openssl-3.5.0-beta1.orig/providers/implementations/kdfs/pbkdf2.c +++ openssl-3.5.0-beta1/providers/implementations/kdfs/pbkdf2.c @@ -36,6 +36,21 @@ #define KDF_PBKDF2_MAX_KEY_LEN_DIGEST_RATIO 0xFFFFFFFF #define KDF_PBKDF2_MIN_ITERATIONS 1000 #define KDF_PBKDF2_MIN_SALT_LEN (128 / 8) +/* The Implementation Guidance for FIPS 140-3 says in section D.N + * "Password-Based Key Derivation for Storage Applications" that "the vendor + * shall document in the module’s Security Policy the length of + * a password/passphrase used in key derivation and establish an upper bound + * for the probability of having this parameter guessed at random. This + * probability shall take into account not only the length of the + * password/passphrase, but also the difficulty of guessing it. The decision on + * the minimum length of a password used for key derivation is the vendor’s, + * but the vendor shall at a minimum informally justify the decision." + * + * We are choosing a minimum password length of 8 bytes, because NIST's ACVP + * testing uses passwords as short as 8 bytes, and requiring longer passwords + * combined with an implicit indicator (i.e., returning an error) would cause + * the module to fail ACVP testing. */ +#define KDF_PBKDF2_MIN_PASSWORD_LEN (8) static OSSL_FUNC_kdf_newctx_fn kdf_pbkdf2_new; static OSSL_FUNC_kdf_dupctx_fn kdf_pbkdf2_dup; @@ -179,8 +194,8 @@ static int pbkdf2_set_membuf(unsigned ch } static int pbkdf2_lower_bound_check_passed(int saltlen, uint64_t iter, - size_t keylen, int *error, - const char **desc) + size_t keylen, size_t passlen, + int *error, const char **desc) { if ((keylen * 8) < KDF_PBKDF2_MIN_KEY_LEN_BITS) { *error = PROV_R_KEY_SIZE_TOO_SMALL; @@ -188,6 +203,12 @@ static int pbkdf2_lower_bound_check_pass *desc = "Key size"; return 0; } + if (passlen < KDF_PBKDF2_MIN_PASSWORD_LEN) { + *error = PROV_R_INVALID_INPUT_LENGTH; + if (desc != NULL) + *desc = "Password length"; + return 0; + } if (saltlen < KDF_PBKDF2_MIN_SALT_LEN) { *error = PROV_R_INVALID_SALT_LENGTH; if (desc != NULL) @@ -205,13 +226,13 @@ static int pbkdf2_lower_bound_check_pass } #ifdef FIPS_MODULE -static int fips_lower_bound_check_passed(KDF_PBKDF2 *ctx, size_t keylen) +static int fips_lower_bound_check_passed(KDF_PBKDF2 *ctx, size_t keylen, size_t passlen) { OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); int error = 0; const char *desc = NULL; int approved = pbkdf2_lower_bound_check_passed(ctx->salt_len, ctx->iter, - keylen, &error, &desc); + keylen, passlen, &error, &desc); if (!approved) { if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE0, libctx, @@ -283,9 +304,15 @@ static int kdf_pbkdf2_set_ctx_params(voi #endif } - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL) + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL) { + if (ctx->lower_bound_checks != 0 + && p->data_size < KDF_PBKDF2_MIN_PASSWORD_LEN) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } if (!pbkdf2_set_membuf(&ctx->pass, &ctx->pass_len, p)) return 0; + } if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) { if (ctx->lower_bound_checks != 0 @@ -400,13 +427,13 @@ static int pbkdf2_derive(KDF_PBKDF2 *ctx } #ifdef FIPS_MODULE - if (!fips_lower_bound_check_passed(ctx, keylen)) + if (!fips_lower_bound_check_passed(ctx, keylen, passlen)) return 0; #else if (lower_bound_checks) { int error = 0; int passed = pbkdf2_lower_bound_check_passed(saltlen, iter, keylen, - &error, NULL); + passlen, &error, NULL); if (!passed) { ERR_raise(ERR_LIB_PROV, error);