This is cribbed, with perimssion, from AWS-LC. The FIPS service indicator[1] signals when an approved service has been completed. [1] FIPS 140-3 IG 2.4.C Change-Id: Ib40210d69b3823f4d2a500b23a1606f8d6942f81 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/52568 Reviewed-by: David Benjamin <davidben@google.com> Commit-Queue: Adam Langley <agl@google.com>fips-20220613
parent
f5d6d24bd6
commit
118a892d2d
28 changed files with 3275 additions and 102 deletions
@ -0,0 +1,89 @@ |
||||
/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* |
||||
* 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_SERVICE_INDICATOR_INTERNAL_H |
||||
#define OPENSSL_HEADER_SERVICE_INDICATOR_INTERNAL_H |
||||
|
||||
#include <openssl/base.h> |
||||
#include <openssl/service_indicator.h> |
||||
|
||||
#if defined(BORINGSSL_FIPS) |
||||
|
||||
// FIPS_service_indicator_update_state records that an approved service has been
|
||||
// invoked.
|
||||
void FIPS_service_indicator_update_state(void); |
||||
|
||||
// FIPS_service_indicator_lock_state and |FIPS_service_indicator_unlock_state|
|
||||
// stop |FIPS_service_indicator_update_state| from actually updating the service
|
||||
// indicator. This is used when a primitive calls a potentially approved
|
||||
// primitive to avoid false positives. For example, just because a key
|
||||
// generation calls |RAND_bytes| (and thus the approved DRBG) doesn't mean that
|
||||
// the key generation operation itself is approved.
|
||||
//
|
||||
// This lock nests: i.e. locking twice is fine so long as each lock is paired
|
||||
// with an unlock. If the (64-bit) counter overflows, the process aborts.
|
||||
void FIPS_service_indicator_lock_state(void); |
||||
void FIPS_service_indicator_unlock_state(void); |
||||
|
||||
// The following functions may call |FIPS_service_indicator_update_state| if
|
||||
// their parameter specifies an approved operation.
|
||||
|
||||
void AEAD_GCM_verify_service_indicator(const EVP_AEAD_CTX *ctx); |
||||
void AEAD_CCM_verify_service_indicator(const EVP_AEAD_CTX *ctx); |
||||
void EC_KEY_keygen_verify_service_indicator(const EC_KEY *eckey); |
||||
void ECDH_verify_service_indicator(const EC_KEY *ec_key); |
||||
void EVP_Cipher_verify_service_indicator(const EVP_CIPHER_CTX *ctx); |
||||
void EVP_DigestSign_verify_service_indicator(const EVP_MD_CTX *ctx); |
||||
void EVP_DigestVerify_verify_service_indicator(const EVP_MD_CTX *ctx); |
||||
void HMAC_verify_service_indicator(const EVP_MD *evp_md); |
||||
void TLSKDF_verify_service_indicator(const EVP_MD *dgst); |
||||
|
||||
#else |
||||
|
||||
// Service indicator functions are no-ops in non-FIPS builds.
|
||||
|
||||
OPENSSL_INLINE void FIPS_service_indicator_update_state(void) {} |
||||
OPENSSL_INLINE void FIPS_service_indicator_lock_state(void) {} |
||||
OPENSSL_INLINE void FIPS_service_indicator_unlock_state(void) {} |
||||
|
||||
OPENSSL_INLINE void AEAD_GCM_verify_service_indicator( |
||||
OPENSSL_UNUSED const EVP_AEAD_CTX *ctx) {} |
||||
|
||||
OPENSSL_INLINE void AEAD_CCM_verify_service_indicator( |
||||
OPENSSL_UNUSED const EVP_AEAD_CTX *ctx) {} |
||||
|
||||
OPENSSL_INLINE void EC_KEY_keygen_verify_service_indicator( |
||||
OPENSSL_UNUSED const EC_KEY *eckey) {} |
||||
|
||||
OPENSSL_INLINE void ECDH_verify_service_indicator( |
||||
OPENSSL_UNUSED const EC_KEY *ec_key) {} |
||||
|
||||
OPENSSL_INLINE void EVP_Cipher_verify_service_indicator( |
||||
OPENSSL_UNUSED const EVP_CIPHER_CTX *ctx) {} |
||||
|
||||
OPENSSL_INLINE void EVP_DigestSign_verify_service_indicator( |
||||
OPENSSL_UNUSED const EVP_MD_CTX *ctx) {} |
||||
|
||||
OPENSSL_INLINE void EVP_DigestVerify_verify_service_indicator( |
||||
OPENSSL_UNUSED const EVP_MD_CTX *ctx) {} |
||||
|
||||
OPENSSL_INLINE void HMAC_verify_service_indicator( |
||||
OPENSSL_UNUSED const EVP_MD *evp_md) {} |
||||
|
||||
OPENSSL_INLINE void TLSKDF_verify_service_indicator( |
||||
OPENSSL_UNUSED const EVP_MD *dgst) {} |
||||
|
||||
#endif // BORINGSSL_FIPS
|
||||
|
||||
#endif // OPENSSL_HEADER_SERVICE_INDICATOR_INTERNAL_H
|
@ -0,0 +1,333 @@ |
||||
/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* |
||||
* 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. */ |
||||
|
||||
#include <openssl/crypto.h> |
||||
#include <openssl/ec.h> |
||||
#include <openssl/ec_key.h> |
||||
#include <openssl/evp.h> |
||||
#include <openssl/service_indicator.h> |
||||
|
||||
#include "../../evp/internal.h" |
||||
#include "../../internal.h" |
||||
#include "internal.h" |
||||
|
||||
#if defined(BORINGSSL_FIPS) |
||||
|
||||
#define STATE_UNLOCKED 0 |
||||
|
||||
// fips_service_indicator_state is a thread-local structure that stores the
|
||||
// state of the FIPS service indicator.
|
||||
struct fips_service_indicator_state { |
||||
// lock_state records the number of times the indicator has been locked.
|
||||
// When it is zero (i.e. |STATE_UNLOCKED|) then the indicator can be updated.
|
||||
uint64_t lock_state; |
||||
// counter is the indicator state. It is incremented when an approved service
|
||||
// completes.
|
||||
uint64_t counter; |
||||
}; |
||||
|
||||
// service_indicator_get returns a pointer to the |fips_service_indicator_state|
|
||||
// for the current thread. It returns NULL on error.
|
||||
//
|
||||
// FIPS 140-3 requires that the module should provide the service indicator
|
||||
// for approved services irrespective of whether the user queries it or not.
|
||||
// Hence, it is lazily initialized in any call to an approved service.
|
||||
static struct fips_service_indicator_state *service_indicator_get(void) { |
||||
struct fips_service_indicator_state *indicator = CRYPTO_get_thread_local( |
||||
OPENSSL_THREAD_LOCAL_FIPS_SERVICE_INDICATOR_STATE); |
||||
|
||||
if (indicator == NULL) { |
||||
indicator = OPENSSL_malloc(sizeof(struct fips_service_indicator_state)); |
||||
if (indicator == NULL) { |
||||
OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE); |
||||
return NULL; |
||||
} |
||||
|
||||
indicator->lock_state = STATE_UNLOCKED; |
||||
indicator->counter = 0; |
||||
|
||||
if (!CRYPTO_set_thread_local( |
||||
OPENSSL_THREAD_LOCAL_FIPS_SERVICE_INDICATOR_STATE, indicator, |
||||
OPENSSL_free)) { |
||||
OPENSSL_PUT_ERROR(CRYPTO, ERR_R_INTERNAL_ERROR); |
||||
return NULL; |
||||
} |
||||
} |
||||
|
||||
return indicator; |
||||
} |
||||
|
||||
static uint64_t service_indicator_get_counter(void) { |
||||
struct fips_service_indicator_state *indicator = service_indicator_get(); |
||||
if (indicator == NULL) { |
||||
return 0; |
||||
} |
||||
return indicator->counter; |
||||
} |
||||
|
||||
uint64_t FIPS_service_indicator_before_call(void) { |
||||
return service_indicator_get_counter(); |
||||
} |
||||
|
||||
uint64_t FIPS_service_indicator_after_call(void) { |
||||
return service_indicator_get_counter(); |
||||
} |
||||
|
||||
void FIPS_service_indicator_update_state(void) { |
||||
struct fips_service_indicator_state *indicator = service_indicator_get(); |
||||
if (indicator && indicator->lock_state == STATE_UNLOCKED) { |
||||
indicator->counter++; |
||||
} |
||||
} |
||||
|
||||
void FIPS_service_indicator_lock_state(void) { |
||||
struct fips_service_indicator_state *indicator = service_indicator_get(); |
||||
if (indicator == NULL) { |
||||
return; |
||||
} |
||||
|
||||
// |FIPS_service_indicator_lock_state| and
|
||||
// |FIPS_service_indicator_unlock_state| should not under/overflow in normal
|
||||
// operation. They are still checked and errors added to facilitate testing in
|
||||
// service_indicator_test.cc. This should only happen if lock/unlock are
|
||||
// called in an incorrect order or multiple times in the same function.
|
||||
const uint64_t new_state = indicator->lock_state + 1; |
||||
if (new_state < indicator->lock_state) { |
||||
// Overflow. This would imply that our call stack length has exceeded a
|
||||
// |uint64_t| which impossible on a 64-bit system.
|
||||
abort(); |
||||
} |
||||
|
||||
indicator->lock_state = new_state; |
||||
} |
||||
|
||||
void FIPS_service_indicator_unlock_state(void) { |
||||
struct fips_service_indicator_state *indicator = service_indicator_get(); |
||||
if (indicator == NULL) { |
||||
return; |
||||
} |
||||
|
||||
if (indicator->lock_state == 0) { |
||||
abort(); |
||||
} |
||||
|
||||
indicator->lock_state--; |
||||
} |
||||
|
||||
void AEAD_GCM_verify_service_indicator(const EVP_AEAD_CTX *ctx) { |
||||
const size_t key_len = EVP_AEAD_key_length(ctx->aead); |
||||
if (key_len == 16 || key_len == 32) { |
||||
FIPS_service_indicator_update_state(); |
||||
} |
||||
} |
||||
|
||||
void AEAD_CCM_verify_service_indicator(const EVP_AEAD_CTX *ctx) { |
||||
if (EVP_AEAD_key_length(ctx->aead) == 16 && ctx->tag_len == 4) { |
||||
FIPS_service_indicator_update_state(); |
||||
} |
||||
} |
||||
|
||||
// is_ec_fips_approved returns one if the curve corresponding to the given NID
|
||||
// is FIPS approved, and zero otherwise.
|
||||
static int is_ec_fips_approved(int curve_nid) { |
||||
switch (curve_nid) { |
||||
case NID_secp224r1: |
||||
case NID_X9_62_prime256v1: |
||||
case NID_secp384r1: |
||||
case NID_secp521r1: |
||||
return 1; |
||||
default: |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
// is_md_fips_approved_for_signing returns one if the given message digest type
|
||||
// is FIPS approved for signing, and zero otherwise.
|
||||
static int is_md_fips_approved_for_signing(int md_type) { |
||||
switch (md_type) { |
||||
case NID_sha224: |
||||
case NID_sha256: |
||||
case NID_sha384: |
||||
case NID_sha512: |
||||
case NID_sha512_256: |
||||
return 1; |
||||
default: |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
// is_md_fips_approved_for_verifying returns one if the given message digest
|
||||
// type is FIPS approved for verifying, and zero otherwise.
|
||||
static int is_md_fips_approved_for_verifying(int md_type) { |
||||
switch (md_type) { |
||||
case NID_sha1: |
||||
case NID_sha224: |
||||
case NID_sha256: |
||||
case NID_sha384: |
||||
case NID_sha512: |
||||
case NID_sha512_256: |
||||
return 1; |
||||
default: |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
static void evp_md_ctx_verify_service_indicator(const EVP_MD_CTX *ctx, |
||||
int rsa_1024_ok, |
||||
int (*md_ok)(int md_type)) { |
||||
if (EVP_MD_CTX_md(ctx) == NULL) { |
||||
// Signature schemes without a prehash are currently never FIPS approved.
|
||||
goto err; |
||||
} |
||||
|
||||
EVP_PKEY_CTX *const pctx = ctx->pctx; |
||||
const EVP_PKEY *const pkey = EVP_PKEY_CTX_get0_pkey(pctx); |
||||
const int pkey_type = EVP_PKEY_id(pkey); |
||||
const int md_type = EVP_MD_CTX_type(ctx); |
||||
|
||||
// EVP_PKEY_RSA_PSS SPKIs aren't supported.
|
||||
if (pkey_type == EVP_PKEY_RSA) { |
||||
// Message digest used in the private key should be of the same type
|
||||
// as the given one, so we extract the MD type from the |EVP_PKEY|
|
||||
// and compare it with the type in |ctx|.
|
||||
const EVP_MD *pctx_md; |
||||
if (!EVP_PKEY_CTX_get_signature_md(pctx, &pctx_md)) { |
||||
goto err; |
||||
} |
||||
if (EVP_MD_type(pctx_md) != md_type) { |
||||
goto err; |
||||
} |
||||
|
||||
int padding; |
||||
if (!EVP_PKEY_CTX_get_rsa_padding(pctx, &padding)) { |
||||
goto err; |
||||
} |
||||
if (padding == RSA_PKCS1_PSS_PADDING) { |
||||
int salt_len; |
||||
const EVP_MD *mgf1_md; |
||||
if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(pctx, &salt_len) || |
||||
!EVP_PKEY_CTX_get_rsa_mgf1_md(pctx, &mgf1_md) || |
||||
(salt_len != -1 && salt_len != (int)EVP_MD_size(pctx_md)) || |
||||
EVP_MD_type(mgf1_md) != md_type) { |
||||
// Only PSS where saltLen == hashLen is tested with ACVP. Cases with
|
||||
// non-standard padding functions are also excluded.
|
||||
goto err; |
||||
} |
||||
} |
||||
|
||||
// The approved RSA key sizes for signing are 2048, 3072 and 4096 bits.
|
||||
// Note: |EVP_PKEY_size| returns the size in bytes.
|
||||
size_t pkey_size = EVP_PKEY_size(ctx->pctx->pkey); |
||||
|
||||
// Check if the MD type and the RSA key size are approved.
|
||||
if (md_ok(md_type) && |
||||
((rsa_1024_ok && pkey_size == 128) || pkey_size == 256 || |
||||
pkey_size == 384 || pkey_size == 512)) { |
||||
FIPS_service_indicator_update_state(); |
||||
} |
||||
} else if (pkey_type == EVP_PKEY_EC) { |
||||
// Check if the MD type and the elliptic curve are approved.
|
||||
if (md_ok(md_type) && is_ec_fips_approved(EC_GROUP_get_curve_name( |
||||
ctx->pctx->pkey->pkey.ec->group))) { |
||||
FIPS_service_indicator_update_state(); |
||||
} |
||||
} |
||||
|
||||
err: |
||||
// Ensure that junk errors aren't left on the queue.
|
||||
ERR_clear_error(); |
||||
} |
||||
|
||||
void EC_KEY_keygen_verify_service_indicator(const EC_KEY *eckey) { |
||||
if (is_ec_fips_approved(EC_GROUP_get_curve_name(eckey->group))) { |
||||
FIPS_service_indicator_update_state(); |
||||
} |
||||
} |
||||
|
||||
void ECDH_verify_service_indicator(const EC_KEY *ec_key) { |
||||
if (is_ec_fips_approved(EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)))) { |
||||
FIPS_service_indicator_update_state(); |
||||
} |
||||
} |
||||
|
||||
void EVP_Cipher_verify_service_indicator(const EVP_CIPHER_CTX *ctx) { |
||||
switch (EVP_CIPHER_CTX_nid(ctx)) { |
||||
case NID_aes_128_ecb: |
||||
case NID_aes_192_ecb: |
||||
case NID_aes_256_ecb: |
||||
|
||||
case NID_aes_128_cbc: |
||||
case NID_aes_192_cbc: |
||||
case NID_aes_256_cbc: |
||||
|
||||
case NID_aes_128_ctr: |
||||
case NID_aes_192_ctr: |
||||
case NID_aes_256_ctr: |
||||
FIPS_service_indicator_update_state(); |
||||
} |
||||
} |
||||
|
||||
void EVP_DigestVerify_verify_service_indicator(const EVP_MD_CTX *ctx) { |
||||
return evp_md_ctx_verify_service_indicator(ctx, /*rsa_1024_ok=*/1, |
||||
is_md_fips_approved_for_verifying); |
||||
} |
||||
|
||||
void EVP_DigestSign_verify_service_indicator(const EVP_MD_CTX *ctx) { |
||||
return evp_md_ctx_verify_service_indicator(ctx, /*rsa_1024_ok=*/0, |
||||
is_md_fips_approved_for_signing); |
||||
} |
||||
|
||||
void HMAC_verify_service_indicator(const EVP_MD *evp_md) { |
||||
switch (evp_md->type) { |
||||
case NID_sha1: |
||||
case NID_sha224: |
||||
case NID_sha256: |
||||
case NID_sha384: |
||||
case NID_sha512: |
||||
case NID_sha512_256: |
||||
FIPS_service_indicator_update_state(); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
void TLSKDF_verify_service_indicator(const EVP_MD *md) { |
||||
// HMAC-MD5, HMAC-SHA1, and HMAC-MD5/HMAC-SHA1 (both used concurrently) are
|
||||
// approved for use in the KDF in TLS 1.0/1.1.
|
||||
// HMAC-SHA{256, 384, 512} are approved for use in the KDF in TLS 1.2.
|
||||
// These Key Derivation functions are to be used in the context of the TLS
|
||||
// protocol.
|
||||
switch (EVP_MD_type(md)) { |
||||
case NID_md5: |
||||
case NID_sha1: |
||||
case NID_md5_sha1: |
||||
case NID_sha256: |
||||
case NID_sha384: |
||||
case NID_sha512: |
||||
FIPS_service_indicator_update_state(); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
#else |
||||
|
||||
uint64_t FIPS_service_indicator_before_call(void) { return 0; } |
||||
|
||||
uint64_t FIPS_service_indicator_after_call(void) { |
||||
// One is returned so that the return value is always greater than zero, the
|
||||
// return value of |FIPS_service_indicator_before_call|. This makes everything
|
||||
// report as "approved" in non-FIPS builds.
|
||||
return 1; |
||||
} |
||||
|
||||
#endif // BORINGSSL_FIPS
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,96 @@ |
||||
/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* |
||||
* 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_SERVICE_INDICATOR_H |
||||
#define OPENSSL_HEADER_SERVICE_INDICATOR_H |
||||
|
||||
#include <openssl/base.h> |
||||
|
||||
#if defined(__cplusplus) |
||||
extern "C" { |
||||
#endif |
||||
|
||||
// FIPS_service_indicator_before_call and |FIPS_service_indicator_after_call|
|
||||
// both currently return the same local thread counter which is slowly
|
||||
// incremented whenever approved services are called. The
|
||||
// |CALL_SERVICE_AND_CHECK_APPROVED| macro is strongly recommended over calling
|
||||
// these functions directly.
|
||||
//
|
||||
// |FIPS_service_indicator_before_call| is intended to be called immediately
|
||||
// before an approved service, while |FIPS_service_indicator_after_call| should
|
||||
// be called immediately after. If the values returned from these two functions
|
||||
// are not equal, this means that the service called inbetween is deemed to be
|
||||
// approved. If the values are still the same, this means the counter has not
|
||||
// been incremented, and the service called is not approved for FIPS.
|
||||
//
|
||||
// In non-FIPS builds, |FIPS_service_indicator_before_call| always returns zero
|
||||
// and |FIPS_service_indicator_after_call| always returns one. Thus calls always
|
||||
// appear to be approved. This is intended to simplify testing.
|
||||
OPENSSL_EXPORT uint64_t FIPS_service_indicator_before_call(void); |
||||
OPENSSL_EXPORT uint64_t FIPS_service_indicator_after_call(void); |
||||
|
||||
#if defined(__cplusplus) |
||||
} |
||||
|
||||
#if !defined(BORINGSSL_NO_CXX) |
||||
|
||||
extern "C++" { |
||||
|
||||
// CALL_SERVICE_AND_CHECK_APPROVED runs |func| and sets |approved| to one of the
|
||||
// |FIPSStatus*| values, above, depending on whether |func| invoked an
|
||||
// approved service. The result of |func| becomes the result of this macro.
|
||||
#define CALL_SERVICE_AND_CHECK_APPROVED(approved, func) \ |
||||
[&] { \
|
||||
bssl::FIPSIndicatorHelper fips_indicator_helper(&approved); \
|
||||
return func; \
|
||||
}() |
||||
|
||||
namespace bssl { |
||||
|
||||
enum class FIPSStatus { |
||||
NOT_APPROVED = 0, |
||||
APPROVED = 1, |
||||
}; |
||||
|
||||
// FIPSIndicatorHelper records whether the service indicator counter advanced
|
||||
// during its lifetime.
|
||||
class FIPSIndicatorHelper { |
||||
public: |
||||
FIPSIndicatorHelper(FIPSStatus *result) |
||||
: result_(result), before_(FIPS_service_indicator_before_call()) { |
||||
*result_ = FIPSStatus::NOT_APPROVED; |
||||
} |
||||
|
||||
~FIPSIndicatorHelper() { |
||||
uint64_t after = FIPS_service_indicator_after_call(); |
||||
if (after != before_) { |
||||
*result_ = FIPSStatus::APPROVED; |
||||
} |
||||
} |
||||
|
||||
FIPSIndicatorHelper(const FIPSIndicatorHelper&) = delete; |
||||
FIPSIndicatorHelper &operator=(const FIPSIndicatorHelper &) = delete; |
||||
|
||||
private: |
||||
FIPSStatus *const result_; |
||||
const uint64_t before_; |
||||
}; |
||||
|
||||
} // namespace bssl
|
||||
} // extern "C++"
|
||||
|
||||
#endif // !BORINGSSL_NO_CXX
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // OPENSSL_HEADER_SERVICE_INDICATOR_H
|
Loading…
Reference in new issue