Skip to content

Commit

Permalink
fips: enforce minimum MAC key length of 112 bits
Browse files Browse the repository at this point in the history
Most regulations require 112 bits. Post 2030 transition to 128 bits is
likely. Implement security check to validate minimum MAC key length.

For FIPS, set it to 112 bits. This is inline with key sizes
recommendations in https://doi.org/10.6028/NIST.SP.800-131Ar2.

Signed-off-by: Dimitri John Ledkov <dimitri.ledkov@surgut.co.uk>
  • Loading branch information
xnox committed Apr 19, 2024
1 parent d657b03 commit 85dcb76
Show file tree
Hide file tree
Showing 9 changed files with 45 additions and 12 deletions.
2 changes: 2 additions & 0 deletions doc/man1/openssl-dgst.pod.in
Expand Up @@ -176,12 +176,14 @@ Following options are supported by both by B<HMAC> and B<gost-mac>:
Specifies MAC key as alphanumeric string (use if key contain printable
characters only). String length must conform to any restrictions of
the MAC algorithm for example exactly 32 chars for gost-mac.
FIPS provider minimum key length is 14 characters (112 bits).

=item B<hexkey>:I<string>

Specifies MAC key in hexadecimal form (two hex digits per byte).
Key length must conform to any restrictions of the MAC algorithm
for example exactly 32 chars for gost-mac.
FIPS provider minimum key length is 28 hexadecimals (112 bits).

=back

Expand Down
8 changes: 4 additions & 4 deletions doc/man1/openssl-kdf.pod.in
Expand Up @@ -149,13 +149,13 @@ SSHKDF, X942KDF-ASN1, X942KDF-CONCAT, X963KDF and SCRYPT.

Use TLS1-PRF to create a hex-encoded derived key from a secret key and seed:

openssl kdf -keylen 16 -kdfopt digest:SHA2-256 -kdfopt key:secret \
-kdfopt seed:seed TLS1-PRF
openssl kdf -keylen 16 -kdfopt digest:SHA2-256 -kdfopt key:16charlongsecret \
-kdfopt seed:a16charslongseed TLS1-PRF

Use HKDF to create a hex-encoded derived key from a secret key, salt and info:

openssl kdf -keylen 10 -kdfopt digest:SHA2-256 -kdfopt key:secret \
-kdfopt salt:salt -kdfopt info:label HKDF
openssl kdf -keylen 10 -kdfopt digest:SHA2-256 -kdfopt key:16charlongsecret \
-kdfopt salt:a16charslongsalt -kdfopt info:label HKDF

Use SSKDF with KMAC to create a hex-encoded derived key from a secret key, salt and info:

Expand Down
2 changes: 2 additions & 0 deletions doc/man1/openssl-mac.pod.in
Expand Up @@ -72,12 +72,14 @@ Common parameter names used by EVP_MAC_CTX_get_params() are:
Specifies the MAC key as an alphanumeric string (use if the key contains
printable characters only).
The string length must conform to any restrictions of the MAC algorithm.
FIPS provider minimum key length is 14 characters (112 bits).
A key must be specified for every MAC algorithm.

=item B<hexkey:>I<string>

Specifies the MAC key in hexadecimal form (two hex digits per byte).
The key length must conform to any restrictions of the MAC algorithm.
FIPS provider minimum key length is 28 hexadecimals (112 bits).
A key must be specified for every MAC algorithm.

=item B<iv:>I<string>
Expand Down
1 change: 1 addition & 0 deletions providers/common/include/prov/securitycheck.h
Expand Up @@ -14,6 +14,7 @@ int ossl_rsa_check_key(OSSL_LIB_CTX *ctx, const RSA *rsa, int operation);
int ossl_ec_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect);
int ossl_dsa_check_key(OSSL_LIB_CTX *ctx, const DSA *dsa, int sign);
int ossl_dh_check_key(OSSL_LIB_CTX *ctx, const DH *dh);
int ossl_mac_check_key(size_t min, size_t requested);

int ossl_digest_is_allowed(OSSL_LIB_CTX *ctx, const EVP_MD *md);
/* With security check enabled it can return -1 to indicate disallowed md */
Expand Down
13 changes: 13 additions & 0 deletions providers/common/securitycheck.c
Expand Up @@ -232,6 +232,19 @@ int ossl_dh_check_key(OSSL_LIB_CTX *ctx, const DH *dh)
}
#endif /* OPENSSL_NO_DH */

/*
* Check for valid MAC key size
*
*/
int ossl_mac_check_key(size_t min, size_t requested)
{
#ifndef FIPS_MODULE
return (requested >= min);
#else
return (requested >= 112);
# endif
}

int ossl_digest_get_approved_nid_with_sha1(OSSL_LIB_CTX *ctx, const EVP_MD *md,
int sha1_allowed)
{
Expand Down
14 changes: 7 additions & 7 deletions providers/fips/self_test_data.inc
Expand Up @@ -279,19 +279,19 @@ static const unsigned char hkdf_secret[] = {
};
static const unsigned char hkdf_salt[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d
};
static const unsigned char hkdf_info[] = {
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9
};
static const unsigned char hkdf_expected[] = {
0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a,
0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a,
0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf,
0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18,
0x58, 0x65
0xcb, 0x95, 0xd0, 0x56, 0xd6, 0xba, 0x6f, 0x08,
0x4d, 0xf0, 0xa0, 0x3a, 0x33, 0x17, 0xbc, 0xca,
0x7f, 0x83, 0x77, 0x32, 0x04, 0xb7, 0x6f, 0x52,
0x7f, 0x4f, 0x06, 0x73, 0x61, 0x68, 0xa5, 0x2b,
0xbc, 0xd8, 0x88, 0x69, 0xa3, 0xa4, 0xe7, 0x97,
0x2d, 0xcd
};
static const ST_KAT_PARAM hkdf_params[] = {
ST_KAT_PARAM_UTF8STRING(OSSL_KDF_PARAM_DIGEST, hkdf_digest),
Expand Down
5 changes: 5 additions & 0 deletions providers/implementations/kdfs/kbkdf.c
Expand Up @@ -43,6 +43,7 @@
#include "prov/provider_ctx.h"
#include "prov/provider_util.h"
#include "prov/providercommon.h"
#include "prov/securitycheck.h"

#include "internal/e_os.h"
#include "internal/params.h"
Expand Down Expand Up @@ -289,6 +290,10 @@ static int kbkdf_derive(void *vctx, unsigned char *key, size_t keylen,
ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
return 0;
}
if (!ossl_mac_check_key(0, ctx->ki_len * 8)) {
ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL);
return 0;
}
/* Could either be missing MAC or missing message digest or missing
* cipher - arbitrarily, I pick this one. */
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MAC);
Expand Down
8 changes: 8 additions & 0 deletions providers/implementations/macs/hmac_prov.c
Expand Up @@ -20,13 +20,16 @@
#include <openssl/params.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/err.h>
#include <openssl/proverr.h>

#include "internal/ssl3_cbc.h"

#include "prov/implementations.h"
#include "prov/provider_ctx.h"
#include "prov/provider_util.h"
#include "prov/providercommon.h"
#include "prov/securitycheck.h"

/*
* Forward declaration of everything implemented here. This is not strictly
Expand Down Expand Up @@ -144,6 +147,11 @@ static int hmac_setkey(struct hmac_data_st *macctx,
{
const EVP_MD *digest;

if (!ossl_mac_check_key(0, keylen * 8)) {
ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL);
return 0;
}

if (macctx->key != NULL)
OPENSSL_secure_clear_free(macctx->key, macctx->keylen);
/* Keep a copy of the key in case we need it for TLS HMAC */
Expand Down
4 changes: 3 additions & 1 deletion providers/implementations/macs/kmac_prov.c
Expand Up @@ -59,6 +59,8 @@
#include "prov/provider_ctx.h"
#include "prov/provider_util.h"
#include "prov/providercommon.h"
#include "prov/securitycheck.h"

#include "internal/cryptlib.h" /* ossl_assert */

/*
Expand Down Expand Up @@ -251,7 +253,7 @@ static int kmac_setkey(struct kmac_data_st *kctx, const unsigned char *key,
const EVP_MD *digest = ossl_prov_digest_md(&kctx->digest);
int w = EVP_MD_get_block_size(digest);

if (keylen < KMAC_MIN_KEY || keylen > KMAC_MAX_KEY) {
if (!ossl_mac_check_key(KMAC_MIN_KEY * 8, keylen * 8) || keylen > KMAC_MAX_KEY) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
Expand Down

0 comments on commit 85dcb76

Please sign in to comment.