Make FFDH self tests lazy.

Change-Id: I7ac046a2422d79b77a231ab65325402658144390
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/51566
Reviewed-by: David Benjamin <davidben@google.com>
fips-20220613
Adam Langley 3 years ago committed by Adam Langley
parent 3053b739ba
commit 4b55af0fc5
  1. 14
      crypto/fipsmodule/dh/dh.c
  2. 36
      crypto/fipsmodule/dh/internal.h
  3. 95
      crypto/fipsmodule/self_check/self_check.c
  4. 6
      crypto/internal.h

@ -64,6 +64,7 @@
#include <openssl/mem.h>
#include <openssl/thread.h>
#include "internal.h"
#include "../../internal.h"
#include "../bn/internal.h"
@ -186,6 +187,8 @@ int DH_set_length(DH *dh, unsigned priv_length) {
}
int DH_generate_key(DH *dh) {
boringssl_ensure_ffdh_self_test();
int ok = 0;
int generate_new_key = 0;
BN_CTX *ctx = NULL;
@ -322,7 +325,8 @@ static int dh_compute_key(DH *dh, BIGNUM *out_shared_key,
return ret;
}
int DH_compute_key_padded(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
int dh_compute_key_padded_no_self_test(unsigned char *out,
const BIGNUM *peers_key, DH *dh) {
BN_CTX *ctx = BN_CTX_new();
if (ctx == NULL) {
return -1;
@ -343,7 +347,15 @@ int DH_compute_key_padded(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
return ret;
}
int DH_compute_key_padded(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
boringssl_ensure_ffdh_self_test();
return dh_compute_key_padded_no_self_test(out, peers_key, dh);
}
int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
boringssl_ensure_ffdh_self_test();
BN_CTX *ctx = BN_CTX_new();
if (ctx == NULL) {
return -1;

@ -0,0 +1,36 @@
/* Copyright (c) 2022, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_DH_INTERNAL_H
#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_DH_INTERNAL_H
#include <openssl/base.h>
#if defined(__cplusplus)
extern "C" {
#endif
// dh_compute_key_padded_no_self_test does the same as |DH_compute_key_padded|,
// but doesn't try to run the self-test first. This is for use in the self tests
// themselves, to prevent an infinite loop.
int dh_compute_key_padded_no_self_test(unsigned char *out,
const BIGNUM *peers_key, DH *dh);
#if defined(__cplusplus)
}
#endif
#endif // OPENSSL_HEADER_CRYPTO_FIPSMODULE_DH_INTERNAL_H

@ -31,6 +31,7 @@
#include <openssl/sha.h>
#include "../../internal.h"
#include "../dh/internal.h"
#include "../ec/internal.h"
#include "../ecdsa/internal.h"
#include "../rand/internal.h"
@ -534,40 +535,7 @@ err:
return ret;
}
#if defined(BORINGSSL_FIPS)
static void run_self_test_rsa(void) {
if (!boringssl_self_test_rsa()) {
BORINGSSL_FIPS_abort();
}
}
DEFINE_STATIC_ONCE(g_self_test_once_rsa);
void boringssl_ensure_rsa_self_test(void) {
CRYPTO_once(g_self_test_once_rsa_bss_get(), run_self_test_rsa);
}
static void run_self_test_ecc(void) {
if (!boringssl_self_test_ecc()) {
BORINGSSL_FIPS_abort();
}
}
DEFINE_STATIC_ONCE(g_self_test_once_ecc);
void boringssl_ensure_ecc_self_test(void) {
CRYPTO_once(g_self_test_once_ecc_bss_get(), run_self_test_ecc);
}
#endif // BORINGSSL_FIPS
// Startup self tests.
//
// These tests are run at process start when in FIPS mode.
static int boringssl_self_test_slow(void) {
static int boringssl_self_test_ffdh(void) {
int ret = 0;
DH *dh = NULL;
BIGNUM *ffdhe2048_value = NULL;
@ -628,7 +596,8 @@ static int boringssl_self_test_slow(void) {
dh = self_test_dh();
uint8_t dh_out[sizeof(kDHOutput)];
if (dh == NULL || ffdhe2048_value == NULL || sizeof(dh_out) != DH_size(dh) ||
DH_compute_key_padded(dh_out, ffdhe2048_value, dh) != sizeof(dh_out) ||
dh_compute_key_padded_no_self_test(dh_out, ffdhe2048_value, dh) !=
sizeof(dh_out) ||
!check_test(kDHOutput, dh_out, sizeof(dh_out), "FFC DH")) {
fprintf(stderr, "FFDH failed.\n");
goto err;
@ -643,6 +612,51 @@ err:
return ret;
}
#if defined(BORINGSSL_FIPS)
static void run_self_test_rsa(void) {
if (!boringssl_self_test_rsa()) {
BORINGSSL_FIPS_abort();
}
}
DEFINE_STATIC_ONCE(g_self_test_once_rsa);
void boringssl_ensure_rsa_self_test(void) {
CRYPTO_once(g_self_test_once_rsa_bss_get(), run_self_test_rsa);
}
static void run_self_test_ecc(void) {
if (!boringssl_self_test_ecc()) {
BORINGSSL_FIPS_abort();
}
}
DEFINE_STATIC_ONCE(g_self_test_once_ecc);
void boringssl_ensure_ecc_self_test(void) {
CRYPTO_once(g_self_test_once_ecc_bss_get(), run_self_test_ecc);
}
static void run_self_test_ffdh(void) {
if (!boringssl_self_test_ffdh()) {
BORINGSSL_FIPS_abort();
}
}
DEFINE_STATIC_ONCE(g_self_test_once_ffdh);
void boringssl_ensure_ffdh_self_test(void) {
CRYPTO_once(g_self_test_once_ffdh_bss_get(), run_self_test_ffdh);
}
#endif // BORINGSSL_FIPS
// Startup self tests.
//
// These tests are run at process start when in FIPS mode.
int boringssl_self_test_sha256(void) {
static const uint8_t kInput[16] = {
0xff, 0x3b, 0x85, 0x7d, 0xa7, 0x23, 0x6a, 0x2b,
@ -930,10 +944,10 @@ err:
int BORINGSSL_self_test(void) {
if (!boringssl_self_test_fast() ||
!boringssl_self_test_slow() ||
// When requested to run self tests, also run the lazy tests.
!boringssl_self_test_rsa() ||
!boringssl_self_test_ecc()) {
!boringssl_self_test_ecc() ||
!boringssl_self_test_ffdh()) {
return 0;
}
@ -942,12 +956,7 @@ int BORINGSSL_self_test(void) {
#if defined(BORINGSSL_FIPS)
int boringssl_self_test_startup(void) {
if (!boringssl_self_test_fast() ||
!boringssl_self_test_slow()) {
return 0;
}
return 1;
return boringssl_self_test_fast();
}
#endif

@ -957,12 +957,18 @@ void boringssl_ensure_rsa_self_test(void);
// address space if unsuccessful.
void boringssl_ensure_ecc_self_test(void);
// boringssl_ensure_ffdh_self_test checks whether the FFDH self-test has been
// run in this address space. If not, it runs it and crashes the address space
// if unsuccessful.
void boringssl_ensure_ffdh_self_test(void);
#else
// Outside of FIPS mode, the lazy tests are no-ops.
OPENSSL_INLINE void boringssl_ensure_rsa_self_test(void) {}
OPENSSL_INLINE void boringssl_ensure_ecc_self_test(void) {}
OPENSSL_INLINE void boringssl_ensure_ffdh_self_test(void) {}
#endif // FIPS

Loading…
Cancel
Save