From b9c80ecf851e58d2983c8fbb8d0ce28e3c8dc2e1 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Jun 03 2020 14:30:12 +0000 Subject: Add FIPS selftest for PBKDF2 and KBKDF Also more adjustments to the FIPS DH handling --- diff --git a/openssl-1.1.1-fips-dh.patch b/openssl-1.1.1-fips-dh.patch index cf59ca5..37efa98 100644 --- a/openssl-1.1.1-fips-dh.patch +++ b/openssl-1.1.1-fips-dh.patch @@ -2115,7 +2115,7 @@ diff -up openssl-1.1.1g/crypto/dh/dh_local.h.fips-dh openssl-1.1.1g/crypto/dh/dh +void dh_cache_nid(DH *dh); diff -up openssl-1.1.1g/crypto/dh/dh_rfc7919.c.fips-dh openssl-1.1.1g/crypto/dh/dh_rfc7919.c --- openssl-1.1.1g/crypto/dh/dh_rfc7919.c.fips-dh 2020-04-21 14:22:39.000000000 +0200 -+++ openssl-1.1.1g/crypto/dh/dh_rfc7919.c 2020-05-25 18:41:00.483262376 +0200 ++++ openssl-1.1.1g/crypto/dh/dh_rfc7919.c 2020-05-27 10:05:05.828687005 +0200 @@ -7,6 +7,8 @@ * https://www.openssl.org/source/license.html */ @@ -2125,161 +2125,173 @@ diff -up openssl-1.1.1g/crypto/dh/dh_rfc7919.c.fips-dh openssl-1.1.1g/crypto/dh/ #include #include "internal/cryptlib.h" #include "dh_local.h" -@@ -14,7 +16,7 @@ +@@ -14,14 +16,19 @@ #include #include "crypto/bn_dh.h" -static DH *dh_param_init(const BIGNUM *p, int32_t nbits) -+static DH *dh_param_init(int nid, const BIGNUM *p, int32_t nbits) ++static DH *dh_param_init(int nid, const BIGNUM *p, const BIGNUM *q, int32_t nbits) { DH *dh = DH_new(); if (dh == NULL) -@@ -22,6 +24,7 @@ static DH *dh_param_init(const BIGNUM *p + return NULL; dh->p = (BIGNUM *)p; ++ /* ++ * We do not set q as it would enable the inefficient and ++ * unnecessary pubkey modular exponentiation check. ++ */ dh->g = (BIGNUM *)&_bignum_const_2; dh->length = nbits; + dh->nid = nid; return dh; } -@@ -29,15 +32,29 @@ DH *DH_new_by_nid(int nid) +@@ -29,46 +36,115 @@ DH *DH_new_by_nid(int nid) { switch (nid) { case NID_ffdhe2048: - return dh_param_init(&_bignum_ffdhe2048_p, 225); -+ return dh_param_init(nid, &_bignum_ffdhe2048_p, 225); ++ return dh_param_init(nid, &_bignum_ffdhe2048_p, &_bignum_ffdhe2048_q, 225); case NID_ffdhe3072: - return dh_param_init(&_bignum_ffdhe3072_p, 275); -+ return dh_param_init(nid, &_bignum_ffdhe3072_p, 275); ++ return dh_param_init(nid, &_bignum_ffdhe3072_p, &_bignum_ffdhe3072_q, 275); case NID_ffdhe4096: - return dh_param_init(&_bignum_ffdhe4096_p, 325); -+ return dh_param_init(nid, &_bignum_ffdhe4096_p, 325); ++ return dh_param_init(nid, &_bignum_ffdhe4096_p, &_bignum_ffdhe4096_q, 325); case NID_ffdhe6144: - return dh_param_init(&_bignum_ffdhe6144_p, 375); -+ return dh_param_init(nid, &_bignum_ffdhe6144_p, 375); ++ return dh_param_init(nid, &_bignum_ffdhe6144_p, &_bignum_ffdhe6144_q, 375); case NID_ffdhe8192: - return dh_param_init(&_bignum_ffdhe8192_p, 400); -+ return dh_param_init(nid, &_bignum_ffdhe8192_p, 400); ++ return dh_param_init(nid, &_bignum_ffdhe8192_p, &_bignum_ffdhe8192_q, 400); + case NID_modp_2048: -+ return dh_param_init(nid, &_bignum_modp_2048_p, 225); ++ return dh_param_init(nid, &_bignum_modp_2048_p, &_bignum_modp_2048_q, 225); + case NID_modp_3072: -+ return dh_param_init(nid, &_bignum_modp_3072_p, 275); ++ return dh_param_init(nid, &_bignum_modp_3072_p, &_bignum_modp_3072_q, 275); + case NID_modp_4096: -+ return dh_param_init(nid, &_bignum_modp_4096_p, 325); ++ return dh_param_init(nid, &_bignum_modp_4096_p, &_bignum_modp_4096_q, 325); + case NID_modp_6144: -+ return dh_param_init(nid, &_bignum_modp_6144_p, 375); ++ return dh_param_init(nid, &_bignum_modp_6144_p, &_bignum_modp_6144_q, 375); + case NID_modp_8192: -+ return dh_param_init(nid, &_bignum_modp_8192_p, 400); ++ return dh_param_init(nid, &_bignum_modp_8192_p, &_bignum_modp_8192_q, 400); + case NID_modp_1536: + if (!FIPS_mode()) -+ return dh_param_init(nid, &_bignum_modp_1536_p, 175); ++ return dh_param_init(nid, &_bignum_modp_1536_p, &_bignum_modp_1536_q, 175); + /* fallthrough */ default: DHerr(DH_F_DH_NEW_BY_NID, DH_R_INVALID_PARAMETER_NID); return NULL; -@@ -47,28 +64,91 @@ DH *DH_new_by_nid(int nid) - int DH_get_nid(const DH *dh) + } + } + +-int DH_get_nid(const DH *dh) ++static int dh_match_group(const DH *dh, BIGNUM **qout, int *lout) { int nid; + const BIGNUM *q; ++ int length; if (BN_get_word(dh->g) != 2) return NID_undef; - if (!BN_cmp(dh->p, &_bignum_ffdhe2048_p)) ++ + if (!BN_cmp(dh->p, &_bignum_ffdhe2048_p)) { nid = NID_ffdhe2048; - else if (!BN_cmp(dh->p, &_bignum_ffdhe3072_p)) + q = &_bignum_ffdhe2048_q; ++ length = 225; + } else if (!BN_cmp(dh->p, &_bignum_ffdhe3072_p)) { nid = NID_ffdhe3072; - else if (!BN_cmp(dh->p, &_bignum_ffdhe4096_p)) + q = &_bignum_ffdhe3072_q; ++ length = 275; + } else if (!BN_cmp(dh->p, &_bignum_ffdhe4096_p)) { nid = NID_ffdhe4096; - else if (!BN_cmp(dh->p, &_bignum_ffdhe6144_p)) + q = &_bignum_ffdhe4096_q; ++ length = 325; + } else if (!BN_cmp(dh->p, &_bignum_ffdhe6144_p)) { nid = NID_ffdhe6144; - else if (!BN_cmp(dh->p, &_bignum_ffdhe8192_p)) + q = &_bignum_ffdhe6144_q; ++ length = 375; + } else if (!BN_cmp(dh->p, &_bignum_ffdhe8192_p)) { nid = NID_ffdhe8192; - else + q = &_bignum_ffdhe8192_q; ++ length = 400; + } else if (!BN_cmp(dh->p, &_bignum_modp_2048_p)) { + nid = NID_modp_2048; + q = &_bignum_modp_2048_q; ++ length = 225; + } else if (!BN_cmp(dh->p, &_bignum_modp_3072_p)) { + nid = NID_modp_3072; + q = &_bignum_modp_3072_q; ++ length = 275; + } else if (!BN_cmp(dh->p, &_bignum_modp_4096_p)) { + nid = NID_modp_4096; + q = &_bignum_modp_4096_q; ++ length = 325; + } else if (!BN_cmp(dh->p, &_bignum_modp_6144_p)) { + nid = NID_modp_6144; + q = &_bignum_modp_6144_q; ++ length = 375; + } else if (!BN_cmp(dh->p, &_bignum_modp_8192_p)) { + nid = NID_modp_8192; + q = &_bignum_modp_8192_q; ++ length = 400; + } else if (!FIPS_mode() && !BN_cmp(dh->p, &_bignum_modp_1536_p)) { + nid = NID_modp_1536; + q = &_bignum_modp_1536_q; ++ length = 175; + } else { return NID_undef; -- if (dh->q != NULL) { ++ } ++ + if (dh->q != NULL) { - BIGNUM *q = BN_dup(dh->p); ++ /* Check that q matches the known q. */ ++ if (BN_cmp(dh->q, q)) ++ return NID_undef; ++ } else if (qout != NULL) { ++ *qout = (BIGNUM *)q; + } - /* Check q = p * 2 + 1 we already know q is odd, so just shift right */ - if (q == NULL || !BN_rshift1(q, q) || !BN_cmp(dh->q, q)) -+ if (dh->q != NULL) { -+ /* Check that q matches the known q. */ -+ if (BN_cmp(dh->q, q)) - nid = NID_undef; +- nid = NID_undef; - BN_free(q); ++ if (lout != NULL) { ++ *lout = length; } return nid; } + -+void dh_cache_nid(DH *dh) ++int DH_get_nid(const DH *dh) +{ -+ dh->nid = DH_get_nid(dh); -+ -+ switch (dh->nid) { -+ case NID_ffdhe2048: -+ dh->length = 225; -+ break; -+ case NID_ffdhe3072: -+ dh->length = 275; -+ break; -+ case NID_ffdhe4096: -+ dh->length = 325; -+ break; -+ case NID_ffdhe6144: -+ dh->length = 375; -+ break; -+ case NID_ffdhe8192: -+ dh->length = 400; -+ break; -+ case NID_modp_2048: -+ dh->length = 225; -+ break; -+ case NID_modp_3072: -+ dh->length = 275; -+ break; -+ case NID_modp_4096: -+ dh->length = 325; -+ break; -+ case NID_modp_6144: -+ dh->length = 375; -+ break; -+ case NID_modp_8192: -+ dh->length = 400; -+ break; -+ case NID_modp_1536: -+ dh->length = 175; ++ if (dh->nid != NID_undef) { ++ return dh->nid; + } ++ return dh_match_group(dh, NULL, NULL); +} ++ ++void dh_cache_nid(DH *dh) ++{ ++ dh->nid = dh_match_group(dh, NULL, &dh->length); ++} +diff -up openssl-1.1.1g/crypto/evp/p_lib.c.fips-dh openssl-1.1.1g/crypto/evp/p_lib.c +--- openssl-1.1.1g/crypto/evp/p_lib.c.fips-dh 2020-04-21 14:22:39.000000000 +0200 ++++ openssl-1.1.1g/crypto/evp/p_lib.c 2020-05-26 14:51:33.604162226 +0200 +@@ -540,7 +540,8 @@ EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *p + + int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) + { +- int type = DH_get0_q(key) == NULL ? EVP_PKEY_DH : EVP_PKEY_DHX; ++ int type = DH_get0_q(key) == NULL || DH_get_nid(key) != NID_undef ? ++ EVP_PKEY_DH : EVP_PKEY_DHX; + int ret = EVP_PKEY_assign(pkey, type, key); + + if (ret) diff -up openssl-1.1.1g/crypto/objects/obj_dat.h.fips-dh openssl-1.1.1g/crypto/objects/obj_dat.h --- openssl-1.1.1g/crypto/objects/obj_dat.h.fips-dh 2020-05-25 18:41:00.452262115 +0200 +++ openssl-1.1.1g/crypto/objects/obj_dat.h 2020-05-25 18:41:00.485262392 +0200 diff --git a/openssl-1.1.1-kdf-selftest.patch b/openssl-1.1.1-kdf-selftest.patch new file mode 100644 index 0000000..3cb3718 --- /dev/null +++ b/openssl-1.1.1-kdf-selftest.patch @@ -0,0 +1,170 @@ +diff -up openssl-1.1.1g/crypto/fips/build.info.kdf-selftest openssl-1.1.1g/crypto/fips/build.info +--- openssl-1.1.1g/crypto/fips/build.info.kdf-selftest 2020-06-03 16:08:36.274849058 +0200 ++++ openssl-1.1.1g/crypto/fips/build.info 2020-06-03 16:11:05.609079372 +0200 +@@ -5,7 +5,7 @@ SOURCE[../../libcrypto]=\ + fips_post.c fips_drbg_ctr.c fips_drbg_hash.c fips_drbg_hmac.c \ + fips_drbg_lib.c fips_drbg_rand.c fips_drbg_selftest.c fips_rand_lib.c \ + fips_cmac_selftest.c fips_ecdh_selftest.c fips_ecdsa_selftest.c \ +- fips_dh_selftest.c fips_ers.c ++ fips_dh_selftest.c fips_kdf_selftest.c fips_ers.c + + PROGRAMS_NO_INST=\ + fips_standalone_hmac +diff -up openssl-1.1.1g/crypto/fips/fips_kdf_selftest.c.kdf-selftest openssl-1.1.1g/crypto/fips/fips_kdf_selftest.c +--- openssl-1.1.1g/crypto/fips/fips_kdf_selftest.c.kdf-selftest 2020-06-03 16:08:36.337849577 +0200 ++++ openssl-1.1.1g/crypto/fips/fips_kdf_selftest.c 2020-06-03 16:08:36.337849577 +0200 +@@ -0,0 +1,117 @@ ++/* ++ * Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright (c) 2018-2019, Oracle and/or its affiliates. All rights reserved. ++ * ++ * Licensed under the Apache License 2.0 (the "License"). You may not use ++ * this file except in compliance with the License. You can obtain a copy ++ * in the file LICENSE in the source distribution or at ++ * https://www.openssl.org/source/license.html ++ */ ++ ++#include ++#include ++#include ++#include "crypto/fips.h" ++ ++#include ++#include ++ ++#ifdef OPENSSL_FIPS ++int FIPS_selftest_pbkdf2(void) ++{ ++ int ret = 0; ++ EVP_KDF_CTX *kctx; ++ unsigned char out[32]; ++ ++ if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_PBKDF2)) == NULL) { ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_PASS, "password", (size_t)8) <= 0) { ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, "salt", (size_t)4) <= 0) { ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_ITER, 2) <= 0) { ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) { ++ goto err; ++ } ++ if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) { ++ goto err; ++ } ++ ++ { ++ const unsigned char expected[sizeof(out)] = { ++ 0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3, ++ 0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0, ++ 0x2a, 0x30, 0x3f, 0x8e, 0xf3, 0xc2, 0x51, 0xdf, ++ 0xd6, 0xe2, 0xd8, 0x5a, 0x95, 0x47, 0x4c, 0x43 ++ }; ++ if (memcmp(out, expected, sizeof(expected))) { ++ goto err; ++ } ++ } ++ ret = 1; ++ ++err: ++ if (!ret) ++ FIPSerr(FIPS_F_FIPS_SELFTEST_PBKDF2, FIPS_R_SELFTEST_FAILED); ++ EVP_KDF_CTX_free(kctx); ++ return ret; ++} ++ ++/* Test vector from RFC 8009 (AES Encryption with HMAC-SHA2 for Kerberos ++ * 5) appendix A. */ ++int FIPS_selftest_kbkdf(void) ++{ ++ int ret = 0; ++ EVP_KDF_CTX *kctx; ++ char *label = "prf", *prf_input = "test"; ++ static unsigned char input_key[] = { ++ 0x37, 0x05, 0xD9, 0x60, 0x80, 0xC1, 0x77, 0x28, ++ 0xA0, 0xE8, 0x00, 0xEA, 0xB6, 0xE0, 0xD2, 0x3C, ++ }; ++ static unsigned char output[] = { ++ 0x9D, 0x18, 0x86, 0x16, 0xF6, 0x38, 0x52, 0xFE, ++ 0x86, 0x91, 0x5B, 0xB8, 0x40, 0xB4, 0xA8, 0x86, ++ 0xFF, 0x3E, 0x6B, 0xB0, 0xF8, 0x19, 0xB4, 0x9B, ++ 0x89, 0x33, 0x93, 0xD3, 0x93, 0x85, 0x42, 0x95, ++ }; ++ unsigned char result[sizeof(output)] = { 0 }; ++ ++ if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_KB)) == NULL) { ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_MAC_TYPE, EVP_KDF_KB_MAC_TYPE_HMAC) <= 0) { ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) { ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, input_key, sizeof(input_key)) <= 0) { ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, label, strlen(label)) <= 0) { ++ goto err; ++ } ++ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KB_INFO, prf_input, strlen(prf_input)) <= 0) { ++ goto err; ++ } ++ ret = EVP_KDF_derive(kctx, result, sizeof(result)) > 0 ++ && memcmp(result, output, sizeof(output)) == 0; ++err: ++ ++ if (!ret) ++ FIPSerr(FIPS_F_FIPS_SELFTEST_KBKDF, FIPS_R_SELFTEST_FAILED); ++ EVP_KDF_CTX_free(kctx); ++ return ret; ++} ++ ++int FIPS_selftest_kdf(void) ++{ ++ return FIPS_selftest_pbkdf2() && FIPS_selftest_kbkdf(); ++} ++ ++#endif +diff -up openssl-1.1.1g/crypto/fips/fips_post.c.kdf-selftest openssl-1.1.1g/crypto/fips/fips_post.c +--- openssl-1.1.1g/crypto/fips/fips_post.c.kdf-selftest 2020-06-03 16:08:36.332849536 +0200 ++++ openssl-1.1.1g/crypto/fips/fips_post.c 2020-06-03 16:08:36.338849585 +0200 +@@ -111,6 +111,8 @@ int FIPS_selftest(void) + rv = 0; + if (!FIPS_selftest_ecdh()) + rv = 0; ++ if (!FIPS_selftest_kdf()) ++ rv = 0; + return rv; + } + +diff -up openssl-1.1.1g/include/crypto/fips.h.kdf-selftest openssl-1.1.1g/include/crypto/fips.h +--- openssl-1.1.1g/include/crypto/fips.h.kdf-selftest 2020-06-03 16:08:36.330849519 +0200 ++++ openssl-1.1.1g/include/crypto/fips.h 2020-06-03 16:08:36.338849585 +0200 +@@ -72,6 +72,9 @@ void FIPS_drbg_stick(int onoff); + int FIPS_selftest_hmac(void); + int FIPS_selftest_drbg(void); + int FIPS_selftest_cmac(void); ++int FIPS_selftest_kbkdf(void); ++int FIPS_selftest_pbkdf2(void); ++int FIPS_selftest_kdf(void); + + int fips_in_post(void); + +diff -up openssl-1.1.1g/include/openssl/fips.h.kdf-selftest openssl-1.1.1g/include/openssl/fips.h +--- openssl-1.1.1g/include/openssl/fips.h.kdf-selftest 2020-06-03 16:08:36.282849124 +0200 ++++ openssl-1.1.1g/include/openssl/fips.h 2020-06-03 16:08:36.338849585 +0200 +@@ -123,6 +123,8 @@ extern "C" { + # define FIPS_F_FIPS_SELFTEST_DSA 112 + # define FIPS_F_FIPS_SELFTEST_ECDSA 133 + # define FIPS_F_FIPS_SELFTEST_HMAC 113 ++# define FIPS_F_FIPS_SELFTEST_KBKDF 151 ++# define FIPS_F_FIPS_SELFTEST_PBKDF2 152 + # define FIPS_F_FIPS_SELFTEST_SHA1 115 + # define FIPS_F_FIPS_SELFTEST_SHA2 105 + # define FIPS_F_OSSL_ECDSA_SIGN_SIG 143 diff --git a/openssl.spec b/openssl.spec index 714b1d0..3984ecf 100644 --- a/openssl.spec +++ b/openssl.spec @@ -22,7 +22,7 @@ Summary: Utilities from the general purpose cryptography library with TLS implementation Name: openssl Version: 1.1.1g -Release: 7%{?dist} +Release: 8%{?dist} Epoch: 1 # We have to remove certain patented algorithms from the openssl source # tarball with the hobble-openssl script which is included below. @@ -68,6 +68,7 @@ Patch61: openssl-1.1.1-edk2-build.patch Patch62: openssl-1.1.1-fips-curves.patch Patch65: openssl-1.1.1-fips-drbg-selftest.patch Patch66: openssl-1.1.1-fips-dh.patch +Patch67: openssl-1.1.1-kdf-selftest.patch # Backported fixes including security fixes Patch52: openssl-1.1.1-s390x-update.patch Patch53: openssl-1.1.1-fips-crng-test.patch @@ -181,6 +182,7 @@ cp %{SOURCE13} test/ %patch62 -p1 -b .fips-curves %patch65 -p1 -b .drbg-selftest %patch66 -p1 -b .fips-dh +%patch67 -p1 -b .kdf-selftest %build @@ -467,7 +469,10 @@ export LD_LIBRARY_PATH %ldconfig_scriptlets libs %changelog -* Tue May 28 2020 Tomáš Mráz 1.1.1g-7 +* Wed Jun 3 2020 Tomáš Mráz 1.1.1g-8 +- Add FIPS selftest for PBKDF2 and KBKDF + +* Tue May 26 2020 Tomáš Mráz 1.1.1g-7 - Use the well known DH groups in TLS * Mon May 25 2020 Tomáš Mráz 1.1.1g-6