diff --git a/crypto/fipsmodule/aes/key_wrap.c b/crypto/fipsmodule/aes/key_wrap.c index 14cd05f859..852f7f90f4 100644 --- a/crypto/fipsmodule/aes/key_wrap.c +++ b/crypto/fipsmodule/aes/key_wrap.c @@ -96,8 +96,8 @@ int AES_wrap_key(const AES_KEY *key, const uint8_t *iv, uint8_t *out, OPENSSL_memcpy(out + 8 * i, A + 8, 8); } } - AES_verify_service_indicator(NULL, key->rounds); OPENSSL_memcpy(out, A, 8); + FIPS_service_indicator_update_state(); return (int)in_len + 8; } @@ -151,7 +151,7 @@ int AES_unwrap_key(const AES_KEY *key, const uint8_t *iv, uint8_t *out, return -1; } - AES_verify_service_indicator(NULL, key->rounds); + FIPS_service_indicator_update_state(); return (int)in_len - 8; } @@ -208,7 +208,7 @@ int AES_wrap_key_padded(const AES_KEY *key, uint8_t *out, size_t *out_len, end: FIPS_service_indicator_unlock_state(); if(ret) { - AES_verify_service_indicator(NULL, key->rounds); + FIPS_service_indicator_update_state(); } return ret; } @@ -246,9 +246,9 @@ int AES_unwrap_key_padded(const AES_KEY *key, uint8_t *out, size_t *out_len, } *out_len = constant_time_select_w(ok, claimed_len, 0); - int ret = ok & 1; + const int ret = ok & 1; if(ret) { - AES_verify_service_indicator(NULL, key->rounds); + FIPS_service_indicator_update_state(); } return ret; } diff --git a/crypto/fipsmodule/aes/mode_wrappers.c b/crypto/fipsmodule/aes/mode_wrappers.c index f814e52ac9..03a28ec609 100644 --- a/crypto/fipsmodule/aes/mode_wrappers.c +++ b/crypto/fipsmodule/aes/mode_wrappers.c @@ -73,7 +73,8 @@ void AES_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len, CRYPTO_ctr128_encrypt_ctr32(in, out, len, key, ivec, ecount_buf, num, aes_nohw_ctr32_encrypt_blocks); } - AES_verify_service_indicator(NULL, key->rounds); + + FIPS_service_indicator_update_state(); } void AES_ecb_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key, @@ -86,29 +87,23 @@ void AES_ecb_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key, } else { AES_decrypt(in, out, key); } - AES_verify_service_indicator(NULL, key->rounds); + + FIPS_service_indicator_update_state(); } void AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len, const AES_KEY *key, uint8_t *ivec, const int enc) { if (hwaes_capable()) { aes_hw_cbc_encrypt(in, out, len, key, ivec, enc); - goto end; - } - - if (!vpaes_capable()) { + } else if (!vpaes_capable()) { aes_nohw_cbc_encrypt(in, out, len, key, ivec, enc); - goto end; - } - - if (enc) { + } else if (enc) { CRYPTO_cbc128_encrypt(in, out, len, key, ivec, AES_encrypt); } else { CRYPTO_cbc128_decrypt(in, out, len, key, ivec, AES_decrypt); } -end: - AES_verify_service_indicator(NULL, key->rounds); + FIPS_service_indicator_update_state(); } void AES_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t length, diff --git a/crypto/fipsmodule/cipher/cipher.c b/crypto/fipsmodule/cipher/cipher.c index 0c0ec77f88..87228839f1 100644 --- a/crypto/fipsmodule/cipher/cipher.c +++ b/crypto/fipsmodule/cipher/cipher.c @@ -322,56 +322,50 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len, } int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) { - int n, ret = 0, custom_ret; + int n; unsigned int i, b, bl; - // |ctx->cipher->cipher| calls the static aes encryption function way under - // the hood instead of |EVP_Cipher|, so the service indicator does not need - // locking here. if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { - custom_ret = ctx->cipher->cipher(ctx, out, NULL, 0); - if (custom_ret < 0) { - goto end; - } else { - *out_len = custom_ret; + // When EVP_CIPH_FLAG_CUSTOM_CIPHER is set, the return value of |cipher| is + // the number of bytes written, or -1 on error. Otherwise the return value + // is one on success and zero on error. + const int num_bytes = ctx->cipher->cipher(ctx, out, NULL, 0); + if (num_bytes < 0) { + return 0; } - ret = 1; - goto end; + *out_len = num_bytes; + goto out; } b = ctx->cipher->block_size; assert(b <= sizeof(ctx->buf)); if (b == 1) { *out_len = 0; - ret = 1; - goto end; + goto out; } bl = ctx->buf_len; if (ctx->flags & EVP_CIPH_NO_PADDING) { if (bl) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH); - goto end; + return 0; } *out_len = 0; - ret = 1; - goto end; + goto out; } n = b - bl; for (i = bl; i < b; i++) { ctx->buf[i] = n; } - ret = ctx->cipher->cipher(ctx, out, ctx->buf, b); - if (ret) { - *out_len = b; + if (!ctx->cipher->cipher(ctx, out, ctx->buf, b)) { + return 0; } + *out_len = b; -end: - if(ret > 0) { - AES_verify_service_indicator(ctx, 0); - } - return ret; +out: + EVP_Cipher_verify_service_indicator(ctx); + return 1; } int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len, @@ -448,7 +442,7 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len) { } else { *out_len = i; } - goto success; + goto out; } b = ctx->cipher->block_size; @@ -458,7 +452,7 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len) { return 0; } *out_len = 0; - goto success; + goto out; } if (b > 1) { @@ -492,17 +486,29 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len) { *out_len = 0; } -success: - AES_verify_service_indicator(ctx, 0); +out: + EVP_Cipher_verify_service_indicator(ctx); return 1; } int EVP_Cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in, size_t in_len) { - int ret = ctx->cipher->cipher(ctx, out, in, in_len); - if(ret > 0) { - AES_verify_service_indicator(ctx, 0); + const int ret = ctx->cipher->cipher(ctx, out, in, in_len); + + // |EVP_CIPH_FLAG_CUSTOM_CIPHER| never sets the FIPS indicator via + // |EVP_Cipher| because it's complicated whether the operation has completed + // or not. E.g. AES-GCM with a non-NULL |in| argument hasn't completed an + // operation. Callers should use the |EVP_AEAD| API or, at least, + // |EVP_CipherUpdate| etc. + // + // This call can't be pushed into |EVP_Cipher_verify_service_indicator| + // because whether |ret| indicates success or not depends on whether + // |EVP_CIPH_FLAG_CUSTOM_CIPHER| is set. (This unreasonable, but matches + // OpenSSL.) + if (!(ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) && ret) { + EVP_Cipher_verify_service_indicator(ctx); } + return ret; } diff --git a/crypto/fipsmodule/cipher/e_aes.c b/crypto/fipsmodule/cipher/e_aes.c index 17ece89884..fa56c8bb02 100644 --- a/crypto/fipsmodule/cipher/e_aes.c +++ b/crypto/fipsmodule/cipher/e_aes.c @@ -1105,24 +1105,14 @@ static int aead_aes_gcm_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out, const uint8_t *in_tag, size_t in_tag_len, const uint8_t *ad, size_t ad_len) { struct aead_aes_gcm_ctx *gcm_ctx = (struct aead_aes_gcm_ctx *)&ctx->state; - return aead_aes_gcm_open_gather_impl(gcm_ctx, out, nonce, nonce_len, in, - in_len, in_tag, in_tag_len, ad, ad_len, - ctx->tag_len); -} - -static int aead_aes_gcm_tls_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out, - const uint8_t *nonce, size_t nonce_len, - const uint8_t *in, size_t in_len, - const uint8_t *in_tag, size_t in_tag_len, - const uint8_t *ad, size_t ad_len) { - // We wrap the original generic |aead_aes_gcm_open_gather| in a tls specific - // function, so we can do service indicator checks in tls specific APIs. - if(aead_aes_gcm_open_gather(ctx, out, nonce, nonce_len, in, in_len, in_tag, - in_tag_len, ad, ad_len)) { - AEAD_GCM_verify_service_indicator(ctx); - return 1; + if (!aead_aes_gcm_open_gather_impl(gcm_ctx, out, nonce, nonce_len, in, in_len, + in_tag, in_tag_len, ad, ad_len, + ctx->tag_len)) { + return 0; } - return 0; + + AEAD_GCM_verify_service_indicator(ctx); + return 1; } DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_128_gcm) { @@ -1368,7 +1358,7 @@ DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_128_gcm_tls12) { out->init = aead_aes_gcm_tls12_init; out->cleanup = aead_aes_gcm_cleanup; out->seal_scatter = aead_aes_gcm_tls12_seal_scatter; - out->open_gather = aead_aes_gcm_tls_open_gather; + out->open_gather = aead_aes_gcm_open_gather; } DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_256_gcm_tls12) { @@ -1383,7 +1373,7 @@ DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_256_gcm_tls12) { out->init = aead_aes_gcm_tls12_init; out->cleanup = aead_aes_gcm_cleanup; out->seal_scatter = aead_aes_gcm_tls12_seal_scatter; - out->open_gather = aead_aes_gcm_tls_open_gather; + out->open_gather = aead_aes_gcm_open_gather; } struct aead_aes_gcm_tls13_ctx { @@ -1478,7 +1468,7 @@ DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_128_gcm_tls13) { out->init = aead_aes_gcm_tls13_init; out->cleanup = aead_aes_gcm_cleanup; out->seal_scatter = aead_aes_gcm_tls13_seal_scatter; - out->open_gather = aead_aes_gcm_tls_open_gather; + out->open_gather = aead_aes_gcm_open_gather; } DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_256_gcm_tls13) { @@ -1493,7 +1483,7 @@ DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_256_gcm_tls13) { out->init = aead_aes_gcm_tls13_init; out->cleanup = aead_aes_gcm_cleanup; out->seal_scatter = aead_aes_gcm_tls13_seal_scatter; - out->open_gather = aead_aes_gcm_tls_open_gather; + out->open_gather = aead_aes_gcm_open_gather; } int EVP_has_aes_hardware(void) { diff --git a/crypto/fipsmodule/evp/digestsign.c b/crypto/fipsmodule/evp/digestsign.c index 3017beec26..51c7c204d3 100644 --- a/crypto/fipsmodule/evp/digestsign.c +++ b/crypto/fipsmodule/evp/digestsign.c @@ -170,7 +170,7 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig, FIPS_service_indicator_unlock_state(); if(ret > 0) { - DigestSign_verify_service_indicator(ctx); + EVP_DigestSign_verify_service_indicator(ctx); } return ret; } else { @@ -205,7 +205,7 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, FIPS_service_indicator_unlock_state(); if(ret > 0) { - DigestVerify_verify_service_indicator(ctx); + EVP_DigestVerify_verify_service_indicator(ctx); } return ret; } @@ -241,7 +241,7 @@ int EVP_DigestSign(EVP_MD_CTX *ctx, uint8_t *out_sig, size_t *out_sig_len, end: FIPS_service_indicator_unlock_state(); if(ret > 0) { - DigestSign_verify_service_indicator(ctx); + EVP_DigestSign_verify_service_indicator(ctx); } return ret; } @@ -271,7 +271,7 @@ int EVP_DigestVerify(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len, end: FIPS_service_indicator_unlock_state(); if(ret > 0) { - DigestVerify_verify_service_indicator(ctx); + EVP_DigestVerify_verify_service_indicator(ctx); } return ret; } diff --git a/crypto/fipsmodule/rsa/padding.c b/crypto/fipsmodule/rsa/padding.c index 71091a73a1..5285149e5f 100644 --- a/crypto/fipsmodule/rsa/padding.c +++ b/crypto/fipsmodule/rsa/padding.c @@ -145,26 +145,19 @@ int RSA_padding_check_PKCS1_type_1(uint8_t *out, size_t *out_len, return 1; } -static int rand_nonzero(uint8_t *out, size_t len) { +static void rand_nonzero(uint8_t *out, size_t len) { // |RAND_bytes| calls within the fipsmodule should be wrapped with state lock // functions to avoid updating the service indicator with the DRBG functions. FIPS_service_indicator_lock_state(); - int ret = 0; - if (!RAND_bytes(out, len)) { - goto end; - } + RAND_bytes(out, len); for (size_t i = 0; i < len; i++) { while (out[i] == 0) { - if (!RAND_bytes(out + i, 1)) { - goto end; - } + RAND_bytes(out + i, 1); } } - ret = 1; -end: + FIPS_service_indicator_unlock_state(); - return ret; } int RSA_padding_add_PKCS1_type_2(uint8_t *to, size_t to_len, @@ -184,9 +177,7 @@ int RSA_padding_add_PKCS1_type_2(uint8_t *to, size_t to_len, to[1] = 2; size_t padding_len = to_len - 3 - from_len; - if (!rand_nonzero(to + 2, padding_len)) { - return 0; - } + rand_nonzero(to + 2, padding_len); to[2 + padding_len] = 0; OPENSSL_memcpy(to + to_len - from_len, from, from_len); @@ -318,8 +309,8 @@ static int PKCS1_MGF1(uint8_t *out, size_t len, const uint8_t *seed, ret = 1; err: - FIPS_service_indicator_unlock_state(); EVP_MD_CTX_cleanup(&ctx); + FIPS_service_indicator_unlock_state(); return ret; } @@ -393,8 +384,8 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, size_t to_len, ret = 1; out: - FIPS_service_indicator_unlock_state(); OPENSSL_free(dbmask); + FIPS_service_indicator_unlock_state(); return ret; } @@ -484,10 +475,10 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *out, size_t *out_len, goto err; } - FIPS_service_indicator_unlock_state(); OPENSSL_memcpy(out, db + one_index, mlen); *out_len = mlen; OPENSSL_free(db); + FIPS_service_indicator_unlock_state(); return 1; decoding_err: @@ -495,8 +486,8 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *out, size_t *out_len, // which kind of decoding error happened OPENSSL_PUT_ERROR(RSA, RSA_R_OAEP_DECODING_ERROR); err: - FIPS_service_indicator_unlock_state(); OPENSSL_free(db); + FIPS_service_indicator_unlock_state(); return 0; } @@ -598,9 +589,9 @@ int RSA_verify_PKCS1_PSS_mgf1(const RSA *rsa, const uint8_t *mHash, } err: - FIPS_service_indicator_unlock_state(); OPENSSL_free(DB); EVP_MD_CTX_cleanup(&ctx); + FIPS_service_indicator_unlock_state(); return ret; } @@ -715,8 +706,8 @@ int RSA_padding_add_PKCS1_PSS_mgf1(const RSA *rsa, unsigned char *EM, ret = 1; err: - FIPS_service_indicator_unlock_state(); OPENSSL_free(salt); + FIPS_service_indicator_unlock_state(); return ret; } diff --git a/crypto/fipsmodule/service_indicator/internal.h b/crypto/fipsmodule/service_indicator/internal.h index 31de014549..fe6f9f1957 100644 --- a/crypto/fipsmodule/service_indicator/internal.h +++ b/crypto/fipsmodule/service_indicator/internal.h @@ -9,13 +9,6 @@ #if defined(AWSLC_FIPS) -#define STATE_UNLOCKED 0 - -struct fips_service_indicator_state { - uint64_t lock_state; - uint64_t counter; -}; - // Only to be used internally, it is not intended for the user to update the // state. This function is used to update the service indicator state, if the // service is deemed to be approved. @@ -39,43 +32,69 @@ void FIPS_service_indicator_update_state(void); 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 AES_CMAC_verify_service_indicator(const CMAC_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 EVP_PKEY_keygen_verify_service_indicator(const EVP_PKEY *pkey); +void HMAC_verify_service_indicator(const EVP_MD *evp_md); +void TLSKDF_verify_service_indicator(const EVP_MD *dgst); + #else -// Service indicator functions are not intended for use during non-FIPS mode. -// If these functions are run during non-FIPS mode, they will provide no -// operations. +// 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) { } -#endif // AWSLC_FIPS - -// is_fips_build is similar to |FIPS_mode| but returns 1 including in the case -// of #if defined(OPENSSL_ASAN) -int is_fips_build(void); +// Service indicator check functions listed below are optimized to not do extra +// checks, when not in FIPS mode. Arguments are cast with |OPENSSL_UNUSED| in an +// attempt to avoid unused warnings. +OPENSSL_INLINE void AEAD_GCM_verify_service_indicator( + OPENSSL_UNUSED const EVP_AEAD_CTX *ctx) {} -// Service indicator check functions parameters are assumed to be not NULL. +OPENSSL_INLINE void AEAD_CCM_verify_service_indicator( + OPENSSL_UNUSED const EVP_AEAD_CTX *ctx) {} -void AES_verify_service_indicator(const EVP_CIPHER_CTX *ctx, const unsigned key_rounds); +OPENSSL_INLINE void AES_CMAC_verify_service_indicator( + OPENSSL_UNUSED const CMAC_CTX *ctx) {} -void AEAD_GCM_verify_service_indicator(const EVP_AEAD_CTX *ctx); +OPENSSL_INLINE void EC_KEY_keygen_verify_service_indicator( + OPENSSL_UNUSED const EC_KEY *eckey) {} -void AEAD_CCM_verify_service_indicator(const EVP_AEAD_CTX *ctx); +OPENSSL_INLINE void ECDH_verify_service_indicator( + OPENSSL_UNUSED const EC_KEY *ec_key) {} -void AES_CMAC_verify_service_indicator(const CMAC_CTX *ctx); +OPENSSL_INLINE void EVP_Cipher_verify_service_indicator( + OPENSSL_UNUSED const EVP_CIPHER_CTX *ctx) {} -void HMAC_verify_service_indicator(const EVP_MD *evp_md); +OPENSSL_INLINE void EVP_DigestSign_verify_service_indicator( + OPENSSL_UNUSED const EVP_MD_CTX *ctx) {} -void EVP_PKEY_keygen_verify_service_indicator(const EVP_PKEY *pkey); +OPENSSL_INLINE void EVP_DigestVerify_verify_service_indicator( + OPENSSL_UNUSED const EVP_MD_CTX *ctx) {} -void DigestSign_verify_service_indicator(const EVP_MD_CTX *ctx); +OPENSSL_INLINE void EVP_PKEY_keygen_verify_service_indicator( + OPENSSL_UNUSED const EVP_PKEY *pkey) {} -void DigestVerify_verify_service_indicator(const EVP_MD_CTX *ctx); +OPENSSL_INLINE void HMAC_verify_service_indicator( + OPENSSL_UNUSED const EVP_MD *evp_md) {} -void ECDH_verify_service_indicator(const EC_KEY *ec_key); +OPENSSL_INLINE void TLSKDF_verify_service_indicator( + OPENSSL_UNUSED const EVP_MD *dgst) {} -void TLSKDF_verify_service_indicator(const EVP_MD *dgst); +#endif // AWSLC_FIPS -void EC_KEY_keygen_verify_service_indicator(EC_KEY *eckey); +// is_fips_build is similar to |FIPS_mode| but returns 1 including in the case +// of #if defined(OPENSSL_ASAN) +int is_fips_build(void); #endif // AWSLC_HEADER_SERVICE_INDICATOR_INTERNAL_H diff --git a/crypto/fipsmodule/service_indicator/service_indicator.c b/crypto/fipsmodule/service_indicator/service_indicator.c index 7c1bbb4841..4418b2cbfa 100644 --- a/crypto/fipsmodule/service_indicator/service_indicator.c +++ b/crypto/fipsmodule/service_indicator/service_indicator.c @@ -19,15 +19,30 @@ int is_fips_build(void) { #if defined(AWSLC_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 * FIPS_service_indicator_get(void) { - struct fips_service_indicator_state *indicator = - CRYPTO_get_thread_local(AWSLC_THREAD_LOCAL_FIPS_SERVICE_INDICATOR_STATE); +static struct fips_service_indicator_state * service_indicator_get(void) { + struct fips_service_indicator_state *indicator = CRYPTO_get_thread_local( + AWSLC_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); @@ -37,17 +52,19 @@ static struct fips_service_indicator_state * FIPS_service_indicator_get(void) { indicator->lock_state = STATE_UNLOCKED; indicator->counter = 0; - if (!CRYPTO_set_thread_local(AWSLC_THREAD_LOCAL_FIPS_SERVICE_INDICATOR_STATE, - indicator, OPENSSL_free)) { + if (!CRYPTO_set_thread_local( + AWSLC_THREAD_LOCAL_FIPS_SERVICE_INDICATOR_STATE, indicator, + OPENSSL_free)) { OPENSSL_PUT_ERROR(CRYPTO, ERR_R_INTERNAL_ERROR); return NULL; } } + return indicator; } -static uint64_t FIPS_service_indicator_get_counter(void) { - struct fips_service_indicator_state *indicator = FIPS_service_indicator_get(); +static uint64_t service_indicator_get_counter(void) { + struct fips_service_indicator_state *indicator = service_indicator_get(); if (indicator == NULL) { return 0; } @@ -55,27 +72,16 @@ static uint64_t FIPS_service_indicator_get_counter(void) { } uint64_t FIPS_service_indicator_before_call(void) { - return FIPS_service_indicator_get_counter(); + return service_indicator_get_counter(); } uint64_t FIPS_service_indicator_after_call(void) { - return FIPS_service_indicator_get_counter(); -} - -int FIPS_service_indicator_check_approved(uint64_t before, uint64_t after) { - if (before != after) { - return AWSLC_APPROVED; - } - return AWSLC_NOT_APPROVED; + return service_indicator_get_counter(); } void FIPS_service_indicator_update_state(void) { - struct fips_service_indicator_state *indicator = FIPS_service_indicator_get(); - if (indicator == NULL) { - return; - } - - if (indicator->lock_state == STATE_UNLOCKED) { + struct fips_service_indicator_state *indicator = service_indicator_get(); + if (indicator && indicator->lock_state == STATE_UNLOCKED) { indicator->counter++; } } @@ -86,77 +92,44 @@ void FIPS_service_indicator_update_state(void) { // only happen if lock/unlock are called in an incorrect order or multiple times // in the same function. void FIPS_service_indicator_lock_state(void) { - struct fips_service_indicator_state *indicator = FIPS_service_indicator_get(); + struct fips_service_indicator_state *indicator = service_indicator_get(); if (indicator == NULL) { return; } - if (indicator->lock_state + 1 > indicator->lock_state) { - indicator->lock_state++; - } else { - OPENSSL_PUT_ERROR(CRYPTO, ERR_R_OVERFLOW); + // |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 = FIPS_service_indicator_get(); + struct fips_service_indicator_state *indicator = service_indicator_get(); if (indicator == NULL) { return; } - if (indicator->lock_state > 0) { - indicator->lock_state--; - } else { - OPENSSL_PUT_ERROR(CRYPTO, ERR_R_OVERFLOW); + if (indicator->lock_state == 0) { + abort(); } -} -void AES_verify_service_indicator(const EVP_CIPHER_CTX *ctx, - const unsigned key_rounds) { - if (ctx != NULL) { - 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(); - break; - default: - break; - } - } else { - // hwaes_capable when enabled in x86 uses 9, 11, 13 for key rounds. - // hwaes_capable when enabled in ARM uses 10, 12, 14 for key rounds. - // When compiling with different ARM specific platforms, 9, 11, 13 are used - // for key rounds. - switch (key_rounds) { - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - FIPS_service_indicator_update_state(); - break; - default: - break; - } - } + indicator->lock_state--; } void AEAD_GCM_verify_service_indicator(const EVP_AEAD_CTX *ctx) { // We only have support for 128 bit and 256 bit keys for AES-GCM. AES-GCM is // approved only with an internal IV, see SP 800-38D Sec 8.2.2. // Note: |EVP_AEAD_key_length| returns the length in bytes. - size_t key_len = EVP_AEAD_key_length(ctx->aead); + const size_t key_len = EVP_AEAD_key_length(ctx->aead); if (key_len == 16 || key_len == 32) { FIPS_service_indicator_update_state(); } @@ -173,29 +146,14 @@ void AEAD_CCM_verify_service_indicator(const EVP_AEAD_CTX *ctx) { void AES_CMAC_verify_service_indicator(const CMAC_CTX *ctx) { // Only 128 and 256 bit keys are approved for AES-CMAC. // Note: |key_len| is the length in bytes. - size_t key_len = ctx->cipher_ctx.key_len; + const size_t key_len = ctx->cipher_ctx.key_len; if (key_len == 16 || key_len == 32) { FIPS_service_indicator_update_state(); } } -void HMAC_verify_service_indicator(const EVP_MD *evp_md) { - // HMAC with SHA1, SHA224, SHA256, SHA384, and SHA512 are approved. - switch (evp_md->type){ - case NID_sha1: - case NID_sha224: - case NID_sha256: - case NID_sha384: - case NID_sha512: - FIPS_service_indicator_update_state(); - break; - default: - break; - } -} - -// Returns 1 if the curve corresponding to the given NID is FIPS approved, and -// 0 otherwise. Only P-224, P-256, P-384, and P-521 curves are FIPS approved. +// 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: @@ -208,42 +166,9 @@ static int is_ec_fips_approved(int curve_nid) { } } -// Updates the service indicator if the elliptic curve contained in |eckey| -// is FIPS approved, otherwise does nothing. -void EC_KEY_keygen_verify_service_indicator(EC_KEY *eckey) { - int curve_nid = EC_GROUP_get_curve_name(eckey->group); - if (is_ec_fips_approved(curve_nid)) { - FIPS_service_indicator_update_state(); - } -} - -void EVP_PKEY_keygen_verify_service_indicator(const EVP_PKEY *pkey) { - if (pkey->type == EVP_PKEY_RSA || pkey->type== EVP_PKEY_RSA_PSS) { - // 2048, 3072 and 4096 bit keys are approved for RSA key generation. - // EVP_PKEY_size returns the size of the key in bytes. - // Note: |EVP_PKEY_size| returns the length in bytes. - size_t key_size = EVP_PKEY_size(pkey); - switch (key_size) { - case 256: - case 384: - case 512: - FIPS_service_indicator_update_state(); - break; - default: - break; - } - } else if (pkey->type == EVP_PKEY_EC) { - // Note: even though the function is called |EC_GROUP_get_curve_name| - // it actually returns the NID of the curve rather than the name. - int curve_nid = EC_GROUP_get_curve_name(pkey->pkey.ec->group); - if (is_ec_fips_approved(curve_nid)) { - FIPS_service_indicator_update_state(); - } - } -} - -// Returns 1 if the given message digest type is FIPS approved for signing, and -// 0 otherwise. Only SHA2-224, SHA2-256, SHA2-384, and SHA2-512 are approved. +// is_md_fips_approved_for_signing returns one if the given message digest type +// is FIPS approved for signing, and zero otherwise. +// TODO (CryptoAlg-1212): FIPS validate SHA512/256 for signing. static int is_md_fips_approved_for_signing(int md_type) { switch (md_type) { case NID_sha224: @@ -256,50 +181,9 @@ static int is_md_fips_approved_for_signing(int md_type) { } } -void DigestSign_verify_service_indicator(const EVP_MD_CTX *ctx) { - int pkey_type = ctx->pctx->pmeth->pkey_id; - - if (pkey_type == EVP_PKEY_RSA || pkey_type == EVP_PKEY_RSA_PSS) { - // 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 private key - // and compare it with the type in |ctx|. - const EVP_MD *pctx_md; - if (!EVP_PKEY_CTX_get_signature_md(ctx->pctx, &pctx_md)) { - OPENSSL_PUT_ERROR(CRYPTO, ERR_R_INTERNAL_ERROR); - return; - } - int md_type = EVP_MD_CTX_type(ctx); - if (pctx_md->type != md_type) { - return; - } - - // 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 (is_md_fips_approved_for_signing(md_type) && - (pkey_size == 256 || pkey_size == 384 || pkey_size == 512)) { - - FIPS_service_indicator_update_state(); - } - } else if (pkey_type == EVP_PKEY_EC) { - int md_type = EVP_MD_CTX_type(ctx); - // Note: even though the function is called |EC_GROUP_get_curve_name| - // it actually returns the NID of the curve rather than the name. - int curve_nid = EC_GROUP_get_curve_name(ctx->pctx->pkey->pkey.ec->group); - - // Check if the MD type and the elliptic curve are approved. - if (is_md_fips_approved_for_signing(md_type) && - is_ec_fips_approved(curve_nid)) { - FIPS_service_indicator_update_state(); - } - } -} - -// Returns 1 if the given message digest type is FIPS approved for verifying, -// and 0 otherwise. Only SHA1, SHA2-224, SHA2-256, SHA2-384, and SHA2-512 -// are approved. +// is_md_fips_approved_for_verifying returns one if the given message digest +// type is FIPS approved for verifying, and zero otherwise. +// TODO (CryptoAlg-1212): FIPS validate SHA512/256 for verifying. static int is_md_fips_approved_for_verifying(int md_type) { switch (md_type) { case NID_sha1: @@ -313,56 +197,152 @@ static int is_md_fips_approved_for_verifying(int md_type) { } } -void DigestVerify_verify_service_indicator(const EVP_MD_CTX *ctx) { - int pkey_type = ctx->pctx->pmeth->pkey_id; +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); if (pkey_type == EVP_PKEY_RSA || pkey_type == EVP_PKEY_RSA_PSS) { // 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 private key + // 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(ctx->pctx, &pctx_md)) { - OPENSSL_PUT_ERROR(CRYPTO, ERR_R_INTERNAL_ERROR); - return; + if (!EVP_PKEY_CTX_get_signature_md(pctx, &pctx_md)) { + goto err; + } + if (EVP_MD_type(pctx_md) != md_type) { + goto err; } - int md_type = EVP_MD_CTX_type(ctx); - if (pctx_md->type != md_type) { - return; + + 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 verifying are 1024, 2048, 3072, 4096 bits. + // 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 (is_md_fips_approved_for_verifying(md_type) && - (pkey_size == 128 || pkey_size == 256 || + 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) { - int md_type = EVP_MD_CTX_type(ctx); - // Note: even though the function is called |EC_GROUP_get_curve_name| - // it actually returns the NID of the curve rather than the name. - int curve_nid = EC_GROUP_get_curve_name(ctx->pctx->pkey->pkey.ec->group); - // Check if the MD type and the elliptic curve are approved. - if (is_md_fips_approved_for_verifying(md_type) && - is_ec_fips_approved(curve_nid)) { + int curve_nid = EC_GROUP_get_curve_name(pkey->pkey.ec->group); + if (md_ok(md_type) && is_ec_fips_approved(curve_nid)) { FIPS_service_indicator_update_state(); } } + + err: + // Ensure that junk errors aren't left on the queue. + ERR_clear_error(); } -void ECDH_verify_service_indicator(const EC_KEY *ec_key) { - int curve_nid = ec_key->group->curve_name; +// Updates the service indicator if the elliptic curve contained in |eckey| +// is FIPS approved. +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(); + } +} - if (is_ec_fips_approved(curve_nid)) { +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_PKEY_keygen_verify_service_indicator(const EVP_PKEY *pkey) { + if (pkey->type == EVP_PKEY_RSA || pkey->type== EVP_PKEY_RSA_PSS) { + // 2048, 3072 and 4096 bit keys are approved for RSA key generation. + // EVP_PKEY_size returns the size of the key in bytes. + // Note: |EVP_PKEY_size| returns the length in bytes. + size_t key_size = EVP_PKEY_size(pkey); + switch (key_size) { + case 256: + case 384: + case 512: + FIPS_service_indicator_update_state(); + break; + default: + break; + } + } else if (pkey->type == EVP_PKEY_EC) { + // Note: even though the function is called |EC_GROUP_get_curve_name| + // it actually returns the NID of the curve rather than the name. + int curve_nid = EC_GROUP_get_curve_name(pkey->pkey.ec->group); + if (is_ec_fips_approved(curve_nid)) { + 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) { + 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) { + evp_md_ctx_verify_service_indicator(ctx, /*rsa_1024_ok=*/0, + is_md_fips_approved_for_signing); +} + +// TODO (CryptoAlg-1212): FIPS validate SHA512/256 for HMAC. +void HMAC_verify_service_indicator(const EVP_MD *evp_md) { + // HMAC with SHA1, SHA224, SHA256, SHA384, and SHA512 are approved. + switch (evp_md->type){ + case NID_sha1: + case NID_sha224: + case NID_sha256: + case NID_sha384: + case NID_sha512: + FIPS_service_indicator_update_state(); + break; + default: + break; + } +} void TLSKDF_verify_service_indicator(const EVP_MD *dgst) { // HMAC-MD5, HMAC-SHA1, and HMAC-MD5/HMAC-SHA1 (both used concurrently) are @@ -384,43 +364,15 @@ void TLSKDF_verify_service_indicator(const EVP_MD *dgst) { } } - #else uint64_t FIPS_service_indicator_before_call(void) { return 0; } -uint64_t FIPS_service_indicator_after_call(void) { return 0; } - - -// Service indicator check functions listed below are optimized to not do extra -// checks, when not in FIPS mode. Arguments are cast with |OPENSSL_UNUSED| in an -// attempt to avoid unused warnings. -int FIPS_service_indicator_check_approved(OPENSSL_UNUSED uint64_t before, - OPENSSL_UNUSED uint64_t after) { - return AWSLC_APPROVED; +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; } -void AES_verify_service_indicator(OPENSSL_UNUSED const EVP_CIPHER_CTX *ctx, - OPENSSL_UNUSED const unsigned key_rounds) { } - -void AEAD_GCM_verify_service_indicator(OPENSSL_UNUSED const EVP_AEAD_CTX *ctx) { } - -void AEAD_CCM_verify_service_indicator(OPENSSL_UNUSED const EVP_AEAD_CTX *ctx) { } - -void AES_CMAC_verify_service_indicator(OPENSSL_UNUSED const CMAC_CTX *ctx) { } - -void HMAC_verify_service_indicator(OPENSSL_UNUSED const EVP_MD *evp_md) { } - -void EVP_PKEY_keygen_verify_service_indicator(OPENSSL_UNUSED const EVP_PKEY *pkey) { } - -void DigestSign_verify_service_indicator(OPENSSL_UNUSED const EVP_MD_CTX *ctx) { } - -void DigestVerify_verify_service_indicator(OPENSSL_UNUSED const EVP_MD_CTX *ctx) { } - -void ECDH_verify_service_indicator(OPENSSL_UNUSED const EC_KEY *ec_key) { } - -void TLSKDF_verify_service_indicator(OPENSSL_UNUSED const EVP_MD *dgst) { } - -void EC_KEY_keygen_verify_service_indicator(OPENSSL_UNUSED EC_KEY *eckey) { } - #endif // AWSLC_FIPS diff --git a/crypto/fipsmodule/service_indicator/service_indicator_test.cc b/crypto/fipsmodule/service_indicator/service_indicator_test.cc index 5cb01503be..186450e8a0 100644 --- a/crypto/fipsmodule/service_indicator/service_indicator_test.cc +++ b/crypto/fipsmodule/service_indicator/service_indicator_test.cc @@ -29,15 +29,6 @@ #include "../rand/internal.h" #include "../tls/internal.h" -namespace awslc { - template - class TestWithNoErrors : public testing::TestWithParam { - void TearDown() override { - ASSERT_EQ(ERR_get_error(), 0u); - } - }; -} - static const uint8_t kAESKey[16] = { 'A','W','S','-','L','C','C','r','y','p','t','o',' ','K', 'e','y'}; static const uint8_t kPlaintext[64] = { @@ -47,6 +38,36 @@ static const uint8_t kPlaintext[64] = { 'P','l','a','i','n','t','e','x','t','!'}; #if defined(AWSLC_FIPS) + +// kEVPKeyGenShouldCallFIPSFunctions determines whether |EVP_PKEY_keygen_*| +// functions should call the FIPS versions of the key-generation functions. +// AWS-LC sets this to true. +static const bool kEVPKeyGenShouldCallFIPSFunctions = true; + +// kCurveSecp256k1Supported determines whether secp256k1 tests should be run. +// AWS-LC sets this to true. +static const bool kCurveSecp256k1Supported = true; + +// kEVPDeriveSetsServiceIndicator is true if `EVP_PKEY_derive` should set the +// service indicator for some algorithms. +// AWS-LC sets this to true. +static const bool kEVPDeriveSetsServiceIndicator = true; + +template +class TestWithNoErrors : public testing::TestWithParam { + void TearDown() override { + if (ERR_peek_error() != 0) { + auto f = [](const char *str, size_t len, void *unused) -> int { + fprintf(stderr, "%s\n", str); + return 1; + }; + ERR_print_errors_cb(f, nullptr); + ADD_FAILURE(); + ADD_FAILURE(); + } + } +}; + static const uint8_t kAESKey_192[24] = { 'A','W','S','-','L','C','C','r','y','p','t','o',' ','1', '9','2', '-','b', 'i','t',' ','K','e','y' @@ -59,93 +80,30 @@ static const uint8_t kAESKey_256[32] = { static const uint8_t kAESIV[AES_BLOCK_SIZE] = {0}; -static void hex_dump(const uint8_t *in, size_t len) { - for (size_t i = 0; i < len; i++) { - fprintf(stderr, "%02x", in[i]); - } -} - -static int check_test(const uint8_t *expected, const uint8_t *actual, - size_t expected_len, const char *name) { - if (OPENSSL_memcmp(actual, expected, expected_len) != 0) { - fprintf(stderr, "%s failed.\nExpected: ", name); - hex_dump(expected, expected_len); - fprintf(stderr, "\nCalculated: "); - hex_dump(actual, expected_len); - fprintf(stderr, "\n"); - fflush(stderr); - return 0; - } - return 1; -} - -static DH *self_test_dh() { - DH *dh = DH_get_rfc7919_2048(); - if (!dh) { - return nullptr; - } - - BIGNUM *priv = BN_new(); - if (!priv) { - goto err; - } - +static bssl::UniquePtr GetDH() { // kFFDHE2048PrivateKeyData is a 225-bit value. (225 because that's the // minimum private key size in // https://tools.ietf.org/html/rfc7919#appendix-A.1.) - static const BN_ULONG kFFDHE2048PrivateKeyData[] = { - TOBN(0x187be36b, 0xd38a4fa1), - TOBN(0x0a152f39, 0x6458f3b8), - TOBN(0x0570187e, 0xc422eeb7), - TOBN(0x00000001, 0x91173f2a), - }; - - priv->d = (BN_ULONG *)kFFDHE2048PrivateKeyData; - priv->width = OPENSSL_ARRAY_SIZE(kFFDHE2048PrivateKeyData); - priv->dmax = OPENSSL_ARRAY_SIZE(kFFDHE2048PrivateKeyData); - priv->neg = 0; - priv->flags |= BN_FLG_STATIC_DATA; - - if (!DH_set0_key(dh, nullptr, priv)) { - goto err; - } - return dh; - - err: - BN_free(priv); - DH_free(dh); - return nullptr; -} - -static void DoEncryptFinal(EVP_CIPHER_CTX *ctx, std::vector *out, - bssl::Span in, int expect_approved) { - int approved = AWSLC_NOT_APPROVED; - size_t max_out = in.size(); - if (EVP_CIPHER_CTX_encrypting(ctx)) { - unsigned block_size = EVP_CIPHER_CTX_block_size(ctx); - max_out += block_size - (max_out % block_size); + static const uint8_t kFFDHE2048PrivateKey[] = { + 0x01, 0x91, 0x17, 0x3f, 0x2a, 0x05, 0x70, 0x18, 0x7e, 0xc4, + 0x22, 0xee, 0xb7, 0x0a, 0x15, 0x2f, 0x39, 0x64, 0x58, 0xf3, + 0xb8, 0x18, 0x7b, 0xe3, 0x6b, 0xd3, 0x8a, 0x4f, 0xa1}; + bssl::UniquePtr priv( + BN_bin2bn(kFFDHE2048PrivateKey, sizeof(kFFDHE2048PrivateKey), nullptr)); + if (!priv) { + return nullptr; } - out->resize(max_out); - - size_t total = 0; - int len; - ASSERT_TRUE(EVP_CipherUpdate(ctx, out->data(), &len, in.data(), in.size())); - total += static_cast(len); - // Check if the overall service is approved by checking |EVP_EncryptFinal_ex| - // or |EVP_DecryptFinal_ex|, which should be the last part of the service. - if (ctx->encrypt) { - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EVP_EncryptFinal_ex(ctx, out->data() + total, &len))); - } else { - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EVP_DecryptFinal_ex(ctx, out->data() + total, &len))); + bssl::UniquePtr dh(DH_get_rfc7919_2048()); + if (!dh || !DH_set0_key(dh.get(), nullptr, priv.get())) { + return nullptr; } - total += static_cast(len); - ASSERT_EQ(approved, expect_approved); - out->resize(total); + priv.release(); // |DH_set0_key| takes ownership on success. + return dh; } static void DoCipherFinal(EVP_CIPHER_CTX *ctx, std::vector *out, - bssl::Span in, int expect_approved) { - int approved = AWSLC_NOT_APPROVED; + bssl::Span in, FIPSStatus expect_approved) { + FIPSStatus approved = AWSLC_NOT_APPROVED; size_t max_out = in.size(); if (EVP_CIPHER_CTX_encrypting(ctx)) { unsigned block_size = EVP_CIPHER_CTX_block_size(ctx); @@ -159,85 +117,28 @@ static void DoCipherFinal(EVP_CIPHER_CTX *ctx, std::vector *out, total += static_cast(len); // Check if the overall service is approved by checking |EVP_CipherFinal_ex|, // which should be the last part of the service. - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE( - EVP_CipherFinal_ex(ctx, out->data() + total, &len))); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, EVP_CipherFinal_ex(ctx, out->data() + total, &len)); total += static_cast(len); ASSERT_EQ(approved, expect_approved); out->resize(total); } -static void TestOperation(const EVP_CIPHER *cipher, bool encrypt, - const std::vector &key, - const std::vector &plaintext, - const std::vector &ciphertext, - int expect_approved) { - int approved = AWSLC_NOT_APPROVED; - const std::vector *in, *out; - if (encrypt) { - in = &plaintext; - out = &ciphertext; - } else { - in = &ciphertext; - out = &plaintext; - } - - bssl::ScopedEVP_CIPHER_CTX ctx; - // Test running the EVP_Cipher interfaces one by one directly, and check - // |EVP_EncryptFinal_ex| and |EVP_DecryptFinal_ex| for approval at the end. - ASSERT_TRUE(EVP_CipherInit_ex(ctx.get(), cipher, nullptr, nullptr, - nullptr, encrypt ? 1 : 0)); - std::vector iv(kAESIV, kAESIV + EVP_CIPHER_CTX_iv_length(ctx.get())); - ASSERT_EQ(iv.size(), EVP_CIPHER_CTX_iv_length(ctx.get())); - - ASSERT_TRUE(EVP_CIPHER_CTX_set_key_length(ctx.get(), key.size())); - ASSERT_TRUE(EVP_CipherInit_ex(ctx.get(), cipher, nullptr, key.data(), iv.data(), encrypt ? 1 : 0)); - ASSERT_TRUE(EVP_CIPHER_CTX_set_padding(ctx.get(), 0)); - std::vector encrypt_result; - DoEncryptFinal(ctx.get(), &encrypt_result, *in, expect_approved); - ASSERT_EQ(Bytes(*out), Bytes(encrypt_result)); - - bssl::ScopedEVP_CIPHER_CTX ctx1; - // Test running the EVP_Cipher interfaces one by one directly, and check - // |EVP_CipherFinal_ex| for approval at the end. - ASSERT_TRUE(EVP_CipherInit_ex(ctx1.get(), cipher, nullptr, nullptr, - nullptr, encrypt ? 1 : 0)); - ASSERT_EQ(iv.size(), EVP_CIPHER_CTX_iv_length(ctx1.get())); - - ASSERT_TRUE(EVP_CIPHER_CTX_set_key_length(ctx1.get(), key.size())); - ASSERT_TRUE(EVP_CipherInit_ex(ctx1.get(), cipher, nullptr, key.data(), iv.data(), encrypt ? 1 : 0)); - ASSERT_TRUE(EVP_CIPHER_CTX_set_padding(ctx1.get(), 0)); - std::vector final_result; - DoCipherFinal(ctx1.get(), &final_result, *in, expect_approved); - ASSERT_EQ(Bytes(*out), Bytes(final_result)); - - - // Test using the one-shot |EVP_Cipher| function for approval. - bssl::ScopedEVP_CIPHER_CTX ctx2; - uint8_t output[256]; - ASSERT_TRUE(EVP_CipherInit_ex(ctx2.get(), cipher, nullptr, key.data(), iv.data(), encrypt ? 1 : 0)); - CALL_SERVICE_AND_CHECK_APPROVED(approved, EVP_Cipher(ctx2.get(), output, - in->data(), in->size())); - ASSERT_EQ(approved, expect_approved); - ASSERT_TRUE(check_test(out->data(), output, in->size(), "EVP_Cipher Encryption KAT")); -} - -static const uint8_t KTDES_EDE3_CipherText[64] = { +static const uint8_t kTDES_EDE3_CipherText[64] = { 0x2a, 0x17, 0x79, 0x5a, 0x9b, 0x1d, 0xd8, 0x72, 0x06, 0xc6, 0xe7, 0x55, 0x14, 0xaa, 0x7b, 0x2a, 0x6e, 0xfc, 0x71, 0x29, 0xff, 0x9b, 0x67, 0x73, 0x7c, 0x9e, 0x15, 0x74, 0x80, 0xc8, 0x2f, 0xca, 0x93, 0xaa, 0x8e, 0xba, 0x2c, 0x48, 0x88, 0x51, 0xc7, 0xa4, 0xf4, 0xe3, 0x2b, 0x33, 0xe5, 0xa1, 0x58, 0x0a, 0x08, 0x3c, 0xb9, 0xf6, 0xf1, - 0x20, 0x67, 0x02, 0x49, 0xa0, 0x92, 0x18, 0xde, 0x2b -}; + 0x20, 0x67, 0x02, 0x49, 0xa0, 0x92, 0x18, 0xde, 0x2b}; -static const uint8_t KTDES_EDE3_CBCCipherText[64] = { +static const uint8_t kTDES_EDE3_CBCCipherText[64] = { 0x2a, 0x17, 0x79, 0x5a, 0x9b, 0x1d, 0xd8, 0x72, 0xbf, 0x3f, 0xfd, 0xe4, 0x0d, 0x66, 0x33, 0x49, 0x3b, 0x8c, 0xa6, 0xd0, 0x0a, 0x66, 0xae, 0xf1, 0xd9, 0xa7, 0xd6, 0xfb, 0xa2, 0x39, 0x6f, 0xf6, 0x1b, 0x8f, 0x67, 0xe1, 0x2b, 0x58, 0x1c, 0xb6, 0xa2, 0xec, 0xb3, 0xc2, 0xe6, 0xd1, 0xcc, 0x11, 0x05, 0xdd, 0xee, 0x9d, 0x87, 0x95, 0xe9, - 0x58, 0xc7, 0xef, 0xa4, 0x6d, 0x5e, 0xd6, 0x57, 0x01 -}; + 0x58, 0xc7, 0xef, 0xa4, 0x6d, 0x5e, 0xd6, 0x57, 0x01}; // AES-OFB is not an approved service, and is only used to test we are not // validating un-approved services correctly. @@ -247,8 +148,7 @@ static const uint8_t kAESOFBCiphertext[64] = { 0xc6, 0xa3, 0xe4, 0x94, 0xaf, 0xd4, 0x1b, 0x64, 0x25, 0x65, 0x28, 0x9e, 0x82, 0xba, 0x92, 0xca, 0x75, 0xb3, 0xf3, 0x78, 0x44, 0x87, 0xd6, 0x11, 0xf9, 0x22, 0xa3, 0xf3, 0xc6, 0x1d, 0x30, 0x00, 0x5b, - 0x77, 0x18, 0x38, 0x39, 0x08, 0x5e, 0x0a, 0x56, 0x6b -}; + 0x77, 0x18, 0x38, 0x39, 0x08, 0x5e, 0x0a, 0x56, 0x6b}; static const uint8_t kAESECBCiphertext[64] = { 0xa4, 0xc1, 0x5c, 0x51, 0x2a, 0x2e, 0x2a, 0xda, 0xd9, 0x02, 0x23, @@ -256,8 +156,7 @@ static const uint8_t kAESECBCiphertext[64] = { 0x29, 0x95, 0x48, 0x6c, 0x7f, 0xa9, 0x47, 0x19, 0x0b, 0x54, 0xe5, 0x0f, 0x05, 0x76, 0xbb, 0xd0, 0x1a, 0x6c, 0xab, 0xe9, 0xfd, 0x5b, 0xd8, 0x0b, 0x0a, 0xbd, 0x7f, 0xea, 0xda, 0x52, 0x07, 0x65, 0x13, - 0x6c, 0xbe, 0xfc, 0x36, 0x82, 0x4b, 0x6a, 0xc3, 0xd5 -}; + 0x6c, 0xbe, 0xfc, 0x36, 0x82, 0x4b, 0x6a, 0xc3, 0xd5}; static const uint8_t kAESECBCiphertext_192[64] = { 0x1d, 0xc8, 0xaa, 0xa7, 0x29, 0x01, 0x17, 0x09, 0x72, 0xc6, 0xe9, @@ -265,8 +164,7 @@ static const uint8_t kAESECBCiphertext_192[64] = { 0x7d, 0x60, 0x1b, 0x3e, 0xc7, 0x7b, 0xe3, 0x18, 0xa2, 0x43, 0x59, 0x15, 0x4a, 0xe4, 0x8a, 0x84, 0xda, 0x16, 0x90, 0x7b, 0xfa, 0x64, 0x37, 0x62, 0x19, 0xf1, 0x95, 0x11, 0x61, 0x84, 0xb0, 0x70, 0x49, - 0x72, 0x9f, 0xe7, 0x3a, 0x18, 0x99, 0x01, 0xba, 0xb0 -}; + 0x72, 0x9f, 0xe7, 0x3a, 0x18, 0x99, 0x01, 0xba, 0xb0}; static const uint8_t kAESECBCiphertext_256[64] = { 0x6f, 0x2d, 0x6d, 0x7a, 0xc1, 0x8f, 0x00, 0x9f, 0x2d, 0xcf, 0xba, @@ -274,8 +172,7 @@ static const uint8_t kAESECBCiphertext_256[64] = { 0x49, 0x6e, 0x28, 0x7b, 0x48, 0x57, 0xb5, 0xf5, 0xd8, 0x05, 0x16, 0x0f, 0xea, 0x21, 0x0c, 0x39, 0x78, 0xee, 0x9e, 0x57, 0x3c, 0x40, 0x11, 0x9c, 0xd9, 0x34, 0x97, 0xb9, 0xa6, 0x06, 0x40, 0x60, 0xa2, - 0x0c, 0x01, 0xe3, 0x9c, 0xda, 0x3e, 0xad, 0x99, 0x3d -}; + 0x0c, 0x01, 0xe3, 0x9c, 0xda, 0x3e, 0xad, 0x99, 0x3d}; static const uint8_t kAESCBCCiphertext[64] = { 0xa4, 0xc1, 0x5c, 0x51, 0x2a, 0x2e, 0x2a, 0xda, 0xd9, 0x02, 0x23, @@ -283,8 +180,7 @@ static const uint8_t kAESCBCCiphertext[64] = { 0x06, 0xf1, 0x36, 0xc3, 0x97, 0x73, 0x87, 0xca, 0x44, 0x99, 0x21, 0xb8, 0xdb, 0x93, 0x22, 0x00, 0x89, 0x7c, 0x1c, 0xea, 0x36, 0x23, 0x18, 0xdb, 0xc1, 0x52, 0x8c, 0x23, 0x66, 0x11, 0x0d, 0xa8, 0xe9, - 0xb8, 0x08, 0x8b, 0xaa, 0x81, 0x47, 0x01, 0xa4, 0x4f -}; + 0xb8, 0x08, 0x8b, 0xaa, 0x81, 0x47, 0x01, 0xa4, 0x4f}; static const uint8_t kAESCBCCiphertext_192[64] = { 0x1d, 0xc8, 0xaa, 0xa7, 0x29, 0x01, 0x17, 0x09, 0x72, 0xc6, 0xe9, @@ -292,8 +188,7 @@ static const uint8_t kAESCBCCiphertext_192[64] = { 0x7f, 0xe3, 0xc1, 0x24, 0xea, 0x41, 0xa0, 0x2b, 0x47, 0x2f, 0xae, 0x19, 0xce, 0x0d, 0xfa, 0x90, 0x45, 0x85, 0xce, 0xc4, 0x21, 0x0c, 0x74, 0x38, 0x13, 0xfd, 0x64, 0xba, 0x58, 0x10, 0x37, 0x53, 0x48, - 0x66, 0x02, 0x76, 0xfb, 0xb1, 0x3a, 0x19, 0xce, 0x61 -}; + 0x66, 0x02, 0x76, 0xfb, 0xb1, 0x3a, 0x19, 0xce, 0x61}; static const uint8_t kAESCBCCiphertext_256[64] = { 0x6f, 0x2d, 0x6d, 0x7a, 0xc1, 0x8f, 0x00, 0x9f, 0x2d, 0xcf, 0xba, @@ -301,8 +196,7 @@ static const uint8_t kAESCBCCiphertext_256[64] = { 0x89, 0x26, 0xc7, 0x94, 0x6a, 0xbf, 0xb6, 0x94, 0x05, 0x08, 0x6c, 0x39, 0x07, 0x52, 0xfa, 0x7b, 0xca, 0x7d, 0x9b, 0xbf, 0xb2, 0x43, 0x2b, 0x69, 0xee, 0xc5, 0x68, 0x4c, 0xdd, 0x62, 0xae, 0x8d, 0x7e, - 0x71, 0x0c, 0x8f, 0x11, 0xce, 0x1d, 0x8b, 0xee, 0x94 -}; + 0x71, 0x0c, 0x8f, 0x11, 0xce, 0x1d, 0x8b, 0xee, 0x94}; static const uint8_t kAESCTRCiphertext[64] = { 0x49, 0xf5, 0x6a, 0x7d, 0x3e, 0xd7, 0xb2, 0x47, 0x35, 0xca, 0x54, @@ -310,8 +204,7 @@ static const uint8_t kAESCTRCiphertext[64] = { 0xfd, 0x10, 0x49, 0x1f, 0x2b, 0x11, 0xe9, 0xb0, 0x07, 0xa4, 0x00, 0x56, 0xec, 0x25, 0x53, 0x4d, 0x70, 0x98, 0x38, 0x85, 0x5d, 0x54, 0xab, 0x2c, 0x19, 0x13, 0x6d, 0xf3, 0x0e, 0x6f, 0x48, 0x2f, 0xab, - 0xe1, 0x82, 0xd4, 0x30, 0xa9, 0x16, 0x73, 0x93, 0xc3 -}; + 0xe1, 0x82, 0xd4, 0x30, 0xa9, 0x16, 0x73, 0x93, 0xc3}; static const uint8_t kAESCTRCiphertext_192[64] = { 0x72, 0x7d, 0xbb, 0xd4, 0x8b, 0x16, 0x8b, 0x19, 0xa4, 0xeb, 0xa6, @@ -319,8 +212,7 @@ static const uint8_t kAESCTRCiphertext_192[64] = { 0xea, 0x89, 0x16, 0xd7, 0xa4, 0xb6, 0xbe, 0x1a, 0x78, 0x1c, 0x3d, 0x44, 0x49, 0xa0, 0xf2, 0xb2, 0xb3, 0x82, 0x0f, 0xdd, 0xac, 0xd6, 0xea, 0x6e, 0x1f, 0x09, 0x8d, 0xa5, 0xdb, 0x4f, 0x3f, 0x97, 0x90, - 0x26, 0xed, 0xf6, 0xbb, 0x62, 0xb3, 0x6f, 0x52, 0x67 -}; + 0x26, 0xed, 0xf6, 0xbb, 0x62, 0xb3, 0x6f, 0x52, 0x67}; static const uint8_t kAESCTRCiphertext_256[64] = { 0x4a, 0x87, 0x44, 0x09, 0xf4, 0x1d, 0x80, 0x94, 0x51, 0x9a, 0xe4, @@ -328,8 +220,7 @@ static const uint8_t kAESCTRCiphertext_256[64] = { 0xbb, 0x29, 0x75, 0xc0, 0xb7, 0x23, 0x0d, 0x81, 0x9f, 0x43, 0xaa, 0x78, 0x89, 0xc0, 0xc4, 0x6d, 0x99, 0x0d, 0xb8, 0x9b, 0xc3, 0x25, 0xa6, 0xd1, 0x7c, 0x98, 0x3e, 0xff, 0x06, 0x59, 0x41, 0xcf, 0xb2, - 0xd5, 0x2f, 0x95, 0xea, 0x83, 0xb1, 0x42, 0xb8, 0xb2 -}; + 0xd5, 0x2f, 0x95, 0xea, 0x83, 0xb1, 0x42, 0xb8, 0xb2}; static const uint8_t kAESCFBCiphertext[64] = { 0x49, 0xf5, 0x6a, 0x7d, 0x3e, 0xd7, 0xb2, 0x47, 0x35, 0xca, 0x54, @@ -337,124 +228,88 @@ static const uint8_t kAESCFBCiphertext[64] = { 0xbf, 0x84, 0x91, 0x49, 0xc5, 0xc9, 0xd6, 0xcf, 0x6a, 0x2c, 0x3a, 0x66, 0x99, 0x68, 0xe3, 0xd0, 0x56, 0x05, 0xe7, 0x99, 0x7f, 0xc3, 0xbc, 0x09, 0x13, 0xa6, 0xf0, 0xde, 0x17, 0xf4, 0x85, 0x9a, 0xee, - 0x29, 0xc3, 0x77, 0xab, 0xc4, 0xf6, 0xdb, 0xae, 0x24 -}; + 0x29, 0xc3, 0x77, 0xab, 0xc4, 0xf6, 0xdb, 0xae, 0x24}; -static const uint8_t kAESCCMCiphertext[68] = { - 0x7a, 0x02, 0x5d, 0x48, 0x02, 0x44, 0x78, 0x7f, 0xb4, 0x71, 0x74, - 0x7b, 0xec, 0x4d, 0x90, 0x29, 0x7b, 0xa7, 0x65, 0xbb, 0x3e, 0x80, - 0x41, 0x7e, 0xab, 0xb4, 0x58, 0x22, 0x4f, 0x86, 0xcd, 0xcc, 0xc2, - 0x12, 0xeb, 0x36, 0x39, 0x89, 0xe3, 0x66, 0x2a, 0xbf, 0xe3, 0x6c, - 0x95, 0x60, 0x13, 0x9e, 0x93, 0xcc, 0xb4, 0x06, 0xbe, 0xaf, 0x3f, - 0xba, 0x13, 0x73, 0x09, 0x92, 0xd1, 0x80, 0x73, 0xb3, 0xc3, 0xa3, - 0xa4, 0x8b +static const uint8_t kAESCCMCiphertext[64 + 4] = { + 0x7a, 0x02, 0x5d, 0x48, 0x02, 0x44, 0x78, 0x7f, 0xb4, 0x71, 0x74, 0x7b, + 0xec, 0x4d, 0x90, 0x29, 0x7b, 0xa7, 0x65, 0xbb, 0x3e, 0x80, 0x41, 0x7e, + 0xab, 0xb4, 0x58, 0x22, 0x4f, 0x86, 0xcd, 0xcc, 0xc2, 0x12, 0xeb, 0x36, + 0x39, 0x89, 0xe3, 0x66, 0x2a, 0xbf, 0xe3, 0x6c, 0x95, 0x60, 0x13, 0x9e, + 0x93, 0xcc, 0xb4, 0x06, 0xbe, 0xaf, 0x3f, 0xba, 0x13, 0x73, 0x09, 0x92, + 0xd1, 0x80, 0x73, 0xb3, 0xc3, 0xa3, 0xa4, 0x8b, }; static const uint8_t kAESKWCiphertext[72] = { - 0x44, 0xec, 0x7d, 0x92, 0x2c, 0x9f, 0xf3, 0xe8, 0xac, 0xb1, 0xea, - 0x3d, 0x0a, 0xc7, 0x51, 0x27, 0xe8, 0x03, 0x11, 0x78, 0xe5, 0xaf, - 0x8d, 0xb1, 0x70, 0x96, 0x2e, 0xfa, 0x05, 0x48, 0x48, 0x99, 0x1a, - 0x58, 0xcc, 0xfe, 0x11, 0x36, 0x5d, 0x49, 0x98, 0x1e, 0xbb, 0xd6, - 0x0b, 0xf5, 0xb9, 0x64, 0xa4, 0x30, 0x3e, 0x60, 0xf6, 0xc5, 0xff, - 0x82, 0x30, 0x9a, 0xa7, 0x48, 0x82, 0xe2, 0x00, 0xc1, 0xe9, 0xc2, - 0x73, 0x6f, 0xbc, 0x89, 0x66, 0x9d -}; + 0x44, 0xec, 0x7d, 0x92, 0x2c, 0x9f, 0xf3, 0xe8, 0xac, 0xb1, 0xea, 0x3d, + 0x0a, 0xc7, 0x51, 0x27, 0xe8, 0x03, 0x11, 0x78, 0xe5, 0xaf, 0x8d, 0xb1, + 0x70, 0x96, 0x2e, 0xfa, 0x05, 0x48, 0x48, 0x99, 0x1a, 0x58, 0xcc, 0xfe, + 0x11, 0x36, 0x5d, 0x49, 0x98, 0x1e, 0xbb, 0xd6, 0x0b, 0xf5, 0xb9, 0x64, + 0xa4, 0x30, 0x3e, 0x60, 0xf6, 0xc5, 0xff, 0x82, 0x30, 0x9a, 0xa7, 0x48, + 0x82, 0xe2, 0x00, 0xc1, 0xe9, 0xc2, 0x73, 0x6f, 0xbc, 0x89, 0x66, 0x9d}; static const uint8_t kAESKWPCiphertext[72] = { - 0x29, 0x5e, 0xb9, 0xea, 0x96, 0xa7, 0xa5, 0xca, 0xfa, 0xeb, 0xda, - 0x78, 0x13, 0xea, 0x83, 0xca, 0x41, 0xdb, 0x4d, 0x36, 0x7d, 0x39, - 0x8a, 0xd6, 0xef, 0xd3, 0xd2, 0x2d, 0x3a, 0xc8, 0x55, 0xc8, 0x73, - 0xd7, 0x79, 0x55, 0xad, 0xc0, 0xce, 0xad, 0x12, 0x54, 0x51, 0xf0, - 0x70, 0x76, 0xff, 0xe7, 0x0c, 0xb2, 0x8e, 0xdd, 0xb6, 0x9a, 0x27, - 0x74, 0x98, 0x28, 0xe0, 0xfa, 0x11, 0xe6, 0x3f, 0x86, 0x93, 0x23, - 0xf8, 0x0d, 0xcb, 0xaf, 0x2b, 0xb7 -}; + 0x29, 0x5e, 0xb9, 0xea, 0x96, 0xa7, 0xa5, 0xca, 0xfa, 0xeb, 0xda, 0x78, + 0x13, 0xea, 0x83, 0xca, 0x41, 0xdb, 0x4d, 0x36, 0x7d, 0x39, 0x8a, 0xd6, + 0xef, 0xd3, 0xd2, 0x2d, 0x3a, 0xc8, 0x55, 0xc8, 0x73, 0xd7, 0x79, 0x55, + 0xad, 0xc0, 0xce, 0xad, 0x12, 0x54, 0x51, 0xf0, 0x70, 0x76, 0xff, 0xe7, + 0x0c, 0xb2, 0x8e, 0xdd, 0xb6, 0x9a, 0x27, 0x74, 0x98, 0x28, 0xe0, 0xfa, + 0x11, 0xe6, 0x3f, 0x86, 0x93, 0x23, 0xf8, 0x0d, 0xcb, 0xaf, 0x2b, 0xb7}; -static const uint8_t kAESCMACOutput[16] = { - 0xe7, 0x32, 0x43, 0xb4, 0xae, 0x79, 0x08, 0x86, 0xe7, 0x9f, 0x0d, - 0x3f, 0x88, 0x3f, 0x1a, 0xfd -}; - -// kFFDHE2048PublicValueData is an arbitrary public value, mod -// kFFDHE2048Data. (The private key happens to be 4096.) -static const BN_ULONG kFFDHE2048PublicValueData[] = { - TOBN(0x187be36b, 0xd38a4fa1), TOBN(0x0a152f39, 0x6458f3b8), - TOBN(0x0570187e, 0xc422eeb7), TOBN(0x18af7482, 0x91173f2a), - TOBN(0xe9fdac6a, 0xcff4eaaa), TOBN(0xf6afebb7, 0x6e589d6c), - TOBN(0xf92f8e9a, 0xb7e33fb0), TOBN(0x70acf2aa, 0x4cf36ddd), - TOBN(0x561ab426, 0xd07137fd), TOBN(0x5f57d037, 0x430ee91e), - TOBN(0xe3e768c8, 0x60d10b8a), TOBN(0xb14884d8, 0xa18af8ce), - TOBN(0xf8a98014, 0xa12b74e4), TOBN(0x748d407c, 0x3437b7a8), - TOBN(0x627588c4, 0x9875d5a7), TOBN(0xdd24a127, 0x53c8f09d), - TOBN(0x85a997d5, 0x0cd51aec), TOBN(0x44f0c619, 0xce348458), - TOBN(0x9b894b24, 0x5f6b69a1), TOBN(0xae1302f2, 0xf6d4777e), - TOBN(0xe6678eeb, 0x375db18e), TOBN(0x2674e1d6, 0x4fbcbdc8), - TOBN(0xb297a823, 0x6fa93d28), TOBN(0x6a12fb70, 0x7c8c0510), - TOBN(0x5c6d1aeb, 0xdb06f65b), TOBN(0xe8c2954e, 0x4c1804ca), - TOBN(0x06bdeac1, 0xf5500fa7), TOBN(0x6a315604, 0x189cd76b), - TOBN(0xbae7b0b3, 0x6e362dc0), TOBN(0xa57c73bd, 0xdc70fb82), - TOBN(0xfaff50d2, 0x9d573457), TOBN(0x352bd399, 0xbe84058e), -}; +static const uint8_t kAESCMACOutput[16] = {0xe7, 0x32, 0x43, 0xb4, 0xae, 0x79, + 0x08, 0x86, 0xe7, 0x9f, 0x0d, 0x3f, + 0x88, 0x3f, 0x1a, 0xfd}; const uint8_t kDHOutput[2048 / 8] = { - 0x2a, 0xe6, 0xd3, 0xa6, 0x13, 0x58, 0x8e, 0xce, 0x53, 0xaa, 0xf6, 0x5d, - 0x9a, 0xae, 0x02, 0x12, 0xf5, 0x80, 0x3d, 0x06, 0x09, 0x76, 0xac, 0x57, - 0x37, 0x9e, 0xab, 0x38, 0x62, 0x25, 0x05, 0x1d, 0xf3, 0xa9, 0x39, 0x60, - 0xf6, 0xae, 0x90, 0xed, 0x1e, 0xad, 0x6e, 0xe9, 0xe3, 0xba, 0x27, 0xf6, - 0xdb, 0x54, 0xdf, 0xe2, 0xbd, 0xbb, 0x7f, 0xf1, 0x81, 0xac, 0x1a, 0xfa, - 0xdb, 0x87, 0x07, 0x98, 0x76, 0x90, 0x21, 0xf2, 0xae, 0xda, 0x0d, 0x84, - 0x97, 0x64, 0x0b, 0xbf, 0xb8, 0x8d, 0x10, 0x46, 0xe2, 0xd5, 0xca, 0x1b, - 0xbb, 0xe5, 0x37, 0xb2, 0x3b, 0x35, 0xd3, 0x1b, 0x65, 0xea, 0xae, 0xf2, - 0x03, 0xe2, 0xb6, 0xde, 0x22, 0xb7, 0x86, 0x49, 0x79, 0xfe, 0xd7, 0x16, - 0xf7, 0xdc, 0x9c, 0x59, 0xf5, 0xb7, 0x70, 0xc0, 0x53, 0x42, 0x6f, 0xb1, - 0xd2, 0x4e, 0x00, 0x25, 0x4b, 0x2d, 0x5a, 0x9b, 0xd0, 0xe9, 0x27, 0x43, - 0xcc, 0x00, 0x66, 0xea, 0x94, 0x7a, 0x0b, 0xb9, 0x89, 0x0c, 0x5e, 0x94, - 0xb8, 0x3a, 0x78, 0x9c, 0x4d, 0x84, 0xe6, 0x32, 0x2c, 0x38, 0x7c, 0xf7, - 0x43, 0x9c, 0xd8, 0xb8, 0x1c, 0xce, 0x24, 0x91, 0x20, 0x67, 0x7a, 0x54, - 0x1f, 0x7e, 0x86, 0x7f, 0xa1, 0xc1, 0x03, 0x4e, 0x2c, 0x26, 0x71, 0xb2, - 0x06, 0x30, 0xb3, 0x6c, 0x15, 0xcc, 0xac, 0x25, 0xe5, 0x37, 0x3f, 0x24, - 0x8f, 0x2a, 0x89, 0x5e, 0x3d, 0x43, 0x94, 0xc9, 0x36, 0xae, 0x40, 0x00, - 0x6a, 0x0d, 0xb0, 0x6e, 0x8b, 0x2e, 0x70, 0x57, 0xe1, 0x88, 0x53, 0xd6, - 0x06, 0x80, 0x2a, 0x4e, 0x5a, 0xf0, 0x1e, 0xaa, 0xcb, 0xab, 0x06, 0x0e, - 0x27, 0x0f, 0xd9, 0x88, 0xd9, 0x01, 0xe3, 0x07, 0xeb, 0xdf, 0xc3, 0x12, - 0xe3, 0x40, 0x88, 0x7b, 0x5f, 0x59, 0x78, 0x6e, 0x26, 0x20, 0xc3, 0xdf, - 0xc8, 0xe4, 0x5e, 0xb8 -}; + 0x83, 0xf0, 0xd8, 0x4f, 0xdb, 0xe7, 0x65, 0xb6, 0x80, 0x6f, 0xa3, 0x22, + 0x9b, 0x33, 0x1c, 0x87, 0x89, 0xc8, 0x1d, 0x2c, 0xa1, 0xba, 0xa3, 0xb8, + 0xdf, 0xad, 0x42, 0xea, 0x9a, 0x75, 0xfe, 0xbf, 0xc1, 0xa8, 0xf6, 0xda, + 0xec, 0xdf, 0x48, 0x61, 0x7d, 0x7f, 0x3d, 0xab, 0xbd, 0xda, 0xd1, 0xd3, + 0xd8, 0xaf, 0x44, 0x4a, 0xba, 0x3f, 0x0e, 0x99, 0x8d, 0x11, 0xdc, 0x63, + 0xb1, 0xe0, 0x65, 0xf2, 0xb9, 0x82, 0x81, 0x8c, 0x88, 0x75, 0x8f, 0xa0, + 0x94, 0x52, 0x2a, 0x2f, 0x2d, 0x10, 0xb1, 0xf4, 0xd2, 0xdd, 0x0f, 0x8a, + 0x7e, 0x49, 0x7b, 0x1e, 0xfd, 0x8c, 0x78, 0xf9, 0x11, 0xdf, 0x80, 0x8b, + 0x2e, 0x86, 0x34, 0xbf, 0x4b, 0xca, 0x13, 0x3e, 0x85, 0x63, 0xeb, 0xe4, + 0xff, 0xec, 0xb0, 0xe8, 0x83, 0xf6, 0x2c, 0x45, 0x21, 0x90, 0x34, 0x9c, + 0x9d, 0x9d, 0xfe, 0x1a, 0x48, 0x53, 0xef, 0x97, 0xd5, 0xea, 0x6a, 0x65, + 0xf5, 0xe9, 0x9f, 0x91, 0x4f, 0xb4, 0x43, 0xe7, 0x1f, 0x0a, 0x2e, 0xdb, + 0xe6, 0x84, 0x30, 0xdb, 0xad, 0xe4, 0xaf, 0x2c, 0xf9, 0x93, 0xe8, 0x0a, + 0xab, 0x7f, 0x1c, 0xde, 0xb3, 0x80, 0xb6, 0x02, 0x42, 0xba, 0x18, 0x0d, + 0x0f, 0xc2, 0x1d, 0xa4, 0x4b, 0x2b, 0x84, 0x74, 0x10, 0x97, 0x6d, 0xdc, + 0xfa, 0x99, 0xdc, 0xba, 0xf2, 0xcb, 0x1b, 0xe8, 0x1a, 0xba, 0x0c, 0x67, + 0x60, 0x07, 0x87, 0xcc, 0xc6, 0x0d, 0xef, 0x56, 0x07, 0x80, 0x55, 0xae, + 0x03, 0xa3, 0x62, 0x31, 0x4c, 0x50, 0xf7, 0xf6, 0x87, 0xb3, 0x8d, 0xe2, + 0x11, 0x86, 0xe7, 0x9d, 0x98, 0x3c, 0x2a, 0x6c, 0x8a, 0xf0, 0xa7, 0x73, + 0x33, 0x07, 0x4e, 0x70, 0xee, 0x14, 0x4b, 0xa3, 0xf7, 0x4f, 0x8f, 0x1a, + 0xa2, 0xf6, 0xd1, 0xeb, 0x4d, 0x04, 0xf9, 0x4c, 0x07, 0x36, 0xb1, 0x46, + 0x53, 0x55, 0xb1, 0x23}; static const uint8_t kOutput_md4[MD4_DIGEST_LENGTH] = { - 0xab, 0x6b, 0xda, 0x84, 0xc0, 0x6b, 0xd0, 0x1d, 0x19, 0xc0, 0x08, - 0x11, 0x07, 0x8d, 0xce, 0x0e -}; + 0xab, 0x6b, 0xda, 0x84, 0xc0, 0x6b, 0xd0, 0x1d, + 0x19, 0xc0, 0x08, 0x11, 0x07, 0x8d, 0xce, 0x0e}; static const uint8_t kOutput_md5[MD5_DIGEST_LENGTH] = { - 0xe9, 0x70, 0xa2, 0xf7, 0x9c, 0x55, 0x57, 0xac, 0x4e, 0x7f, 0x6b, - 0xbc, 0xa3, 0xb9, 0xb7, 0xdb -}; + 0xe9, 0x70, 0xa2, 0xf7, 0x9c, 0x55, 0x57, 0xac, + 0x4e, 0x7f, 0x6b, 0xbc, 0xa3, 0xb9, 0xb7, 0xdb}; static const uint8_t kOutput_sha1[SHA_DIGEST_LENGTH] = { - 0xaa, 0x18, 0x71, 0x34, 0x00, 0x71, 0x67, 0x9f, 0xa1, 0x6d, 0x20, - 0x82, 0x91, 0x0f, 0x53, 0x0a, 0xcd, 0x6e, 0xa4, 0x34 -}; + 0xaa, 0x18, 0x71, 0x34, 0x00, 0x71, 0x67, 0x9f, 0xa1, 0x6d, + 0x20, 0x82, 0x91, 0x0f, 0x53, 0x0a, 0xcd, 0x6e, 0xa4, 0x34}; static const uint8_t kOutput_sha224[SHA224_DIGEST_LENGTH] = { - 0x5f, 0x1a, 0x9e, 0x68, 0x4c, 0xb7, 0x42, 0x68, 0xa0, 0x8b, 0x87, - 0xd7, 0x96, 0xb6, 0xcf, 0x1e, 0x4f, 0x85, 0x1c, 0x47, 0xe9, 0x29, - 0xb3, 0xb2, 0x73, 0x72, 0xd2, 0x69 -}; + 0x5f, 0x1a, 0x9e, 0x68, 0x4c, 0xb7, 0x42, 0x68, 0xa0, 0x8b, + 0x87, 0xd7, 0x96, 0xb6, 0xcf, 0x1e, 0x4f, 0x85, 0x1c, 0x47, + 0xe9, 0x29, 0xb3, 0xb2, 0x73, 0x72, 0xd2, 0x69}; static const uint8_t kOutput_sha256[SHA256_DIGEST_LENGTH] = { 0xe7, 0x63, 0x1c, 0xbb, 0x12, 0xb5, 0xbf, 0x4f, 0x99, 0x05, 0x9d, 0x40, 0x15, 0x55, 0x34, 0x9c, 0x26, 0x36, 0xd2, 0xfe, 0x6a, 0xd6, - 0x26, 0xb4, 0x9d, 0x33, 0x07, 0xf5, 0xe6, 0x29, 0x13, 0x92 -}; + 0x26, 0xb4, 0x9d, 0x33, 0x07, 0xf5, 0xe6, 0x29, 0x13, 0x92}; static const uint8_t kOutput_sha384[SHA384_DIGEST_LENGTH] = { - 0x15, 0x81, 0x48, 0x8d, 0x95, 0xf2, 0x66, 0x84, 0x65, 0x94, 0x3e, - 0xb9, 0x8c, 0xda, 0x36, 0x30, 0x2a, 0x85, 0xc0, 0xcd, 0xec, 0x38, - 0xa0, 0x1f, 0x72, 0xe2, 0x68, 0xfe, 0x4e, 0xdb, 0x27, 0x8b, 0x50, - 0x15, 0xe0, 0x24, 0xc3, 0x65, 0xd1, 0x66, 0x2a, 0x3e, 0xe7, 0x00, - 0x16, 0x51, 0xf5, 0x18 -}; + 0x15, 0x81, 0x48, 0x8d, 0x95, 0xf2, 0x66, 0x84, 0x65, 0x94, 0x3e, 0xb9, + 0x8c, 0xda, 0x36, 0x30, 0x2a, 0x85, 0xc0, 0xcd, 0xec, 0x38, 0xa0, 0x1f, + 0x72, 0xe2, 0x68, 0xfe, 0x4e, 0xdb, 0x27, 0x8b, 0x50, 0x15, 0xe0, 0x24, + 0xc3, 0x65, 0xd1, 0x66, 0x2a, 0x3e, 0xe7, 0x00, 0x16, 0x51, 0xf5, 0x18}; static const uint8_t kOutput_sha512[SHA512_DIGEST_LENGTH] = { 0x71, 0xcc, 0xec, 0x03, 0xf8, 0x76, 0xf4, 0x0b, 0xf1, 0x1b, 0x89, @@ -462,71 +317,58 @@ static const uint8_t kOutput_sha512[SHA512_DIGEST_LENGTH] = { 0x12, 0xb9, 0xa8, 0x8c, 0xc5, 0x9d, 0xae, 0x3c, 0x73, 0x43, 0x76, 0x4d, 0x98, 0xed, 0xd0, 0xbe, 0xb4, 0xf9, 0x0b, 0x5c, 0x5d, 0x34, 0x46, 0x30, 0x18, 0xc2, 0x05, 0x88, 0x8a, 0x3c, 0x25, 0xcc, 0x06, - 0xf8, 0x73, 0xb9, 0xe4, 0x18, 0xa8, 0xc2, 0xf0, 0xe5 -}; + 0xf8, 0x73, 0xb9, 0xe4, 0x18, 0xa8, 0xc2, 0xf0, 0xe5}; static const uint8_t kOutput_sha512_256[SHA512_256_DIGEST_LENGTH] = { 0x1a, 0x78, 0x68, 0x6b, 0x69, 0x6d, 0x28, 0x14, 0x6b, 0x37, 0x11, 0x2d, 0xfb, 0x72, 0x35, 0xfa, 0xc1, 0xc4, 0x5f, 0x5c, 0x49, 0x91, - 0x08, 0x95, 0x0b, 0x0f, 0xc9, 0x88, 0x44, 0x12, 0x01, 0x6a -}; + 0x08, 0x95, 0x0b, 0x0f, 0xc9, 0x88, 0x44, 0x12, 0x01, 0x6a}; static const uint8_t kHMACOutput_sha1[SHA_DIGEST_LENGTH] = { - 0x2b, 0xcb, 0x0e, 0xe2, 0xa4, 0x66, 0xad, 0x70, 0xa2, 0xb8, 0x8e, - 0xe2, 0x4c, 0x76, 0xf9, 0x1c, 0x28, 0x07, 0x78, 0xeb -}; + 0x34, 0xac, 0x50, 0x9b, 0xa9, 0x4c, 0x39, 0xef, 0x45, 0xa0, + 0x6b, 0xdc, 0xfc, 0xbd, 0x3d, 0x42, 0xe8, 0x0a, 0x97, 0x86}; static const uint8_t kHMACOutput_sha224[SHA224_DIGEST_LENGTH] = { - 0x68, 0x29, 0x44, 0x26, 0x49, 0x3f, 0x02, 0x27, 0x64, 0xd1, 0x29, - 0xa5, 0x59, 0xcd, 0x2f, 0x79, 0xc7, 0xf1, 0xa8, 0xed, 0x77, 0xe2, - 0x0a, 0xc7, 0x75, 0xba, 0x61, 0xb4 -}; + 0x30, 0x62, 0x97, 0x45, 0x9e, 0xea, 0x62, 0xe4, 0x5d, 0xbb, + 0x7d, 0x25, 0x3f, 0x77, 0x0f, 0x9d, 0xa4, 0xbd, 0x17, 0x96, + 0x23, 0x53, 0xe1, 0x76, 0xf3, 0xf8, 0x9b, 0x74}; static const uint8_t kHMACOutput_sha256[SHA256_DIGEST_LENGTH] = { - 0x0d, 0xb3, 0xca, 0x78, 0x9a, 0x03, 0x6d, 0x23, 0x3c, 0x7f, 0x00, - 0x87, 0x9d, 0x9c, 0x49, 0x4c, 0x65, 0x9d, 0x2d, 0xa3, 0x8d, 0x77, - 0x74, 0x68, 0xd9, 0xd9, 0xa8, 0xa2, 0x65, 0xb2, 0x5e, 0x9e -}; + 0x68, 0x33, 0x3e, 0x74, 0x9a, 0x49, 0xab, 0x77, 0xb4, 0x1a, 0x40, + 0xd8, 0x55, 0x07, 0xa7, 0xb6, 0x48, 0xa1, 0xa5, 0xa9, 0xd1, 0x7b, + 0x85, 0xe9, 0x33, 0x09, 0x16, 0x79, 0xcc, 0xe9, 0x29, 0x97}; static const uint8_t kHMACOutput_sha384[SHA384_DIGEST_LENGTH] = { - 0x3e, 0x76, 0xac, 0x2f, 0x8b, 0x27, 0xea, 0x08, 0xef, 0xa8, 0xa2, - 0xf7, 0x5b, 0xf2, 0x95, 0x0d, 0x71, 0x8f, 0xbf, 0x5f, 0x1e, 0xe6, - 0xef, 0xb6, 0x25, 0x1c, 0xd5, 0x07, 0x05, 0x20, 0x61, 0x9e, 0x71, - 0x8a, 0x02, 0x92, 0xef, 0x59, 0xdf, 0x32, 0x0f, 0x8c, 0xa4, 0x0a, - 0x58, 0x0d, 0x91, 0xd8 -}; + 0xcc, 0x39, 0x22, 0x0e, 0x9f, 0x2e, 0x26, 0x4a, 0xb5, 0xf8, 0x4a, 0x0f, + 0x73, 0x51, 0x26, 0x1a, 0xf2, 0xef, 0x15, 0xf3, 0x5f, 0x77, 0xce, 0xbb, + 0x4c, 0x69, 0x86, 0x0e, 0x1f, 0x5c, 0x4d, 0xc9, 0x96, 0xd9, 0xed, 0x74, + 0x6c, 0x45, 0x05, 0x7a, 0x0e, 0x3f, 0x36, 0x8a, 0xda, 0x2a, 0x35, 0xf9}; static const uint8_t kHMACOutput_sha512[SHA512_DIGEST_LENGTH] = { - 0xeb, 0x8f, 0xe6, 0x4f, 0xcb, 0x40, 0x23, 0xbe, 0xfc, 0x64, 0xd6, - 0x99, 0x3d, 0x22, 0x7d, 0x76, 0x1a, 0x97, 0x69, 0x01, 0xed, 0x04, - 0x87, 0x48, 0xb3, 0xbe, 0xda, 0xc7, 0x19, 0xb9, 0xe2, 0x95, 0x6b, - 0x69, 0xe3, 0x9a, 0x2f, 0x27, 0xfc, 0xfd, 0x2f, 0xb5, 0xcb, 0xa6, - 0xa9, 0xb2, 0xcf, 0xe7, 0x22, 0x4f, 0xf2, 0x0a, 0x72, 0xf5, 0x97, - 0x29, 0x3b, 0x4f, 0xd7, 0xbd, 0xfe, 0x76, 0xea, 0x55 -}; + 0x4c, 0x09, 0x46, 0x50, 0x7c, 0xb3, 0xa1, 0xfa, 0xbc, 0xf2, 0xc4, + 0x4f, 0x1e, 0x3d, 0xa9, 0x0b, 0x29, 0x4e, 0x12, 0x09, 0x09, 0x32, + 0xde, 0x82, 0xa0, 0xab, 0xf6, 0x5e, 0x66, 0x19, 0xd0, 0x86, 0x9a, + 0x92, 0xe3, 0xf9, 0x13, 0xa7, 0xe6, 0xfc, 0x1a, 0x2e, 0x50, 0xda, + 0xf6, 0x8f, 0xb2, 0xd5, 0xb2, 0x6e, 0x97, 0x82, 0x25, 0x5a, 0x1e, + 0xbf, 0x9b, 0x99, 0x8c, 0xf0, 0x37, 0xe6, 0x3d, 0x40}; static const uint8_t kHMACOutput_sha512_256[SHA512_256_DIGEST_LENGTH] = { - 0x2d, 0x7b, 0xe8, 0x12, 0x93, 0xba, 0xc2, 0xb5, 0xc6, 0x73, 0x61, - 0xc1, 0xd0, 0xb8, 0x75, 0xfe, 0x00, 0xd8, 0x3d, 0x7c, 0x31, 0x47, - 0x22, 0x83, 0xdd, 0x7c, 0x3f, 0xb1, 0x97, 0x1e, 0xd3, 0x2c -}; + 0x9c, 0x95, 0x9c, 0x03, 0xc9, 0x8c, 0x90, 0xee, 0x7a, 0xff, 0xed, + 0x26, 0xba, 0x75, 0x90, 0xd0, 0xb9, 0xd4, 0x09, 0xf5, 0x22, 0xd6, + 0xb6, 0xab, 0xa8, 0xb9, 0xae, 0x01, 0x06, 0x37, 0x8f, 0xd1}; static const uint8_t kDRBGEntropy[48] = { - 'B', 'C', 'M', ' ', 'K', 'n', 'o', 'w', 'n', ' ', 'A', 'n', 's', - 'w', 'e', 'r', ' ', 'T', 'e', 's', 't', ' ', 'D', 'B', 'R', 'G', - ' ', 'I', 'n', 'i', 't', 'i', 'a', 'l', ' ', 'E', 'n', 't', 'r', - 'o', 'p', 'y', ' ', ' ', ' ', ' ', ' ', ' ' -}; + 'B', 'C', 'M', ' ', 'K', 'n', 'o', 'w', 'n', ' ', 'A', 'n', + 's', 'w', 'e', 'r', ' ', 'T', 'e', 's', 't', ' ', 'D', 'B', + 'R', 'G', ' ', 'I', 'n', 'i', 't', 'i', 'a', 'l', ' ', 'E', + 'n', 't', 'r', 'o', 'p', 'y', ' ', ' ', ' ', ' ', ' ', ' '}; -static const uint8_t kDRBGPersonalization[18] = { - 'B', 'C', 'M', 'P', 'e', 'r', 's', 'o', 'n', 'a', 'l', 'i', 'z', - 'a', 't', 'i', 'o', 'n' -}; +static const uint8_t kDRBGPersonalization[18] = {'B', 'C', 'M', 'P', 'e', 'r', + 's', 'o', 'n', 'a', 'l', 'i', + 'z', 'a', 't', 'i', 'o', 'n'}; -static const uint8_t kDRBGAD[16] = { - 'B', 'C', 'M', ' ', 'D', 'R', 'B', 'G', ' ', 'K', 'A', 'T', ' ', - 'A', 'D', ' ' -}; +static const uint8_t kDRBGAD[16] = {'B', 'C', 'M', ' ', 'D', 'R', 'B', 'G', + ' ', 'K', 'A', 'T', ' ', 'A', 'D', ' '}; const uint8_t kDRBGOutput[64] = { 0x1d, 0x63, 0xdf, 0x05, 0x51, 0x49, 0x22, 0x46, 0xcd, 0x9b, 0xc5, @@ -534,15 +376,13 @@ const uint8_t kDRBGOutput[64] = { 0x96, 0x33, 0x3d, 0x60, 0xb6, 0x29, 0xd4, 0xbb, 0x6b, 0x44, 0xf9, 0xef, 0xd9, 0xf4, 0xa2, 0xba, 0x48, 0xea, 0x39, 0x75, 0x59, 0x32, 0xf7, 0x31, 0x2c, 0x98, 0x14, 0x2b, 0x49, 0xdf, 0x02, 0xb6, 0x5d, - 0x71, 0x09, 0x50, 0xdb, 0x23, 0xdb, 0xe5, 0x22, 0x95 -}; + 0x71, 0x09, 0x50, 0xdb, 0x23, 0xdb, 0xe5, 0x22, 0x95}; static const uint8_t kDRBGEntropy2[48] = { - 'B', 'C', 'M', ' ', 'K', 'n', 'o', 'w', 'n', ' ', 'A', 'n', 's', - 'w', 'e', 'r', ' ', 'T', 'e', 's', 't', ' ', 'D', 'B', 'R', 'G', - ' ', 'R', 'e', 's', 'e', 'e', 'd', ' ', 'E', 'n', 't', 'r', 'o', - 'p', 'y', ' ', ' ', ' ', ' ', ' ', ' ', ' ' -}; + 'B', 'C', 'M', ' ', 'K', 'n', 'o', 'w', 'n', ' ', 'A', 'n', + 's', 'w', 'e', 'r', ' ', 'T', 'e', 's', 't', ' ', 'D', 'B', + 'R', 'G', ' ', 'R', 'e', 's', 'e', 'e', 'd', ' ', 'E', 'n', + 't', 'r', 'o', 'p', 'y', ' ', ' ', ' ', ' ', ' ', ' ', ' '}; static const uint8_t kDRBGReseedOutput[64] = { 0xa4, 0x77, 0x05, 0xdb, 0x14, 0x11, 0x76, 0x71, 0x42, 0x5b, 0xd8, @@ -571,121 +411,205 @@ static const uint8_t kTLSSeed2[16] = { static const uint8_t kTLSOutput_mdsha1[32] = { 0x36, 0xa9, 0x31, 0xb0, 0x43, 0xe3, 0x64, 0x72, 0xb9, 0x47, 0x54, 0x0d, 0x8a, 0xfc, 0xe3, 0x5c, 0x1c, 0x15, 0x67, 0x7e, 0xa3, 0x5d, - 0xf2, 0x3a, 0x57, 0xfd, 0x50, 0x16, 0xe1, 0xa4, 0xa6, 0x37 + 0xf2, 0x3a, 0x57, 0xfd, 0x50, 0x16, 0xe1, 0xa4, 0xa6, 0x37, }; static const uint8_t kTLSOutput_md[32] = { 0x79, 0xef, 0x46, 0xc4, 0x35, 0xbc, 0xe5, 0xda, 0xd3, 0x66, 0x91, 0xdc, 0x86, 0x09, 0x41, 0x66, 0xf2, 0x0c, 0xeb, 0xe6, 0xab, 0x5c, - 0x58, 0xf4, 0x65, 0xce, 0x2f, 0x5f, 0x4b, 0x34, 0x1e, 0xa1 + 0x58, 0xf4, 0x65, 0xce, 0x2f, 0x5f, 0x4b, 0x34, 0x1e, 0xa1, }; static const uint8_t kTLSOutput_sha1[32] = { 0xbb, 0x0a, 0x73, 0x52, 0xf8, 0x85, 0xd7, 0xbd, 0x12, 0x34, 0x78, 0x3b, 0x54, 0x4c, 0x75, 0xfe, 0xd7, 0x23, 0x6e, 0x22, 0x3f, 0x42, - 0x34, 0x99, 0x57, 0x6b, 0x14, 0xc4, 0xc8, 0xae, 0x9f, 0x4c + 0x34, 0x99, 0x57, 0x6b, 0x14, 0xc4, 0xc8, 0xae, 0x9f, 0x4c, }; static const uint8_t kTLSOutput_sha224[32] = { 0xdd, 0xaf, 0x6f, 0xaa, 0xd9, 0x2b, 0x3d, 0xb9, 0x46, 0x4c, 0x55, 0x8a, 0xf7, 0xa6, 0x9b, 0x0b, 0x35, 0xcc, 0x07, 0xa7, 0x55, 0x5b, - 0x5e, 0x39, 0x12, 0xc0, 0xd4, 0x30, 0xdf, 0x0c, 0xdf, 0x6b + 0x5e, 0x39, 0x12, 0xc0, 0xd4, 0x30, 0xdf, 0x0c, 0xdf, 0x6b, }; static const uint8_t kTLSOutput_sha256[32] = { 0x67, 0x85, 0xde, 0x60, 0xfc, 0x0a, 0x83, 0xe9, 0xa2, 0x2a, 0xb3, 0xf0, 0x27, 0x0c, 0xba, 0xf7, 0xfa, 0x82, 0x3d, 0x14, 0x77, 0x1d, - 0x86, 0x29, 0x79, 0x39, 0x77, 0x8a, 0xd5, 0x0e, 0x9d, 0x32 + 0x86, 0x29, 0x79, 0x39, 0x77, 0x8a, 0xd5, 0x0e, 0x9d, 0x32, }; static const uint8_t kTLSOutput_sha384[32] = { 0x75, 0x15, 0x3f, 0x44, 0x7a, 0xfd, 0x34, 0xed, 0x2b, 0x67, 0xbc, 0xd8, 0x57, 0x96, 0xab, 0xff, 0xf4, 0x0c, 0x05, 0x94, 0x02, 0x23, - 0x81, 0xbf, 0x0e, 0xd2, 0xec, 0x7c, 0xe0, 0xa7, 0xc3, 0x7d + 0x81, 0xbf, 0x0e, 0xd2, 0xec, 0x7c, 0xe0, 0xa7, 0xc3, 0x7d, }; static const uint8_t kTLSOutput_sha512[32] = { 0x68, 0xb9, 0xc8, 0x4c, 0xf5, 0x51, 0xfc, 0x7a, 0x1f, 0x6c, 0xe5, 0x43, 0x73, 0x80, 0x53, 0x7c, 0xae, 0x76, 0x55, 0x67, 0xe0, 0x79, - 0xbf, 0x3a, 0x53, 0x71, 0xb7, 0x9c, 0xb5, 0x03, 0x15, 0x3f + 0xbf, 0x3a, 0x53, 0x71, 0xb7, 0x9c, 0xb5, 0x03, 0x15, 0x3f, }; -static const uint8_t kAESGCMCiphertext_128[64] = { - 0x38, 0x71, 0xcb, 0x61, 0x70, 0x60, 0x13, 0x8b, 0x2f, 0x91, 0x09, - 0x7f, 0x83, 0x20, 0x0f, 0x1f, 0x71, 0xe2, 0x47, 0x46, 0x6f, 0x5f, - 0xa8, 0xad, 0xa8, 0xfc, 0x0a, 0xfd, 0x36, 0x65, 0x84, 0x90, 0x28, - 0x2b, 0xcb, 0x4f, 0x68, 0xae, 0x09, 0xba, 0xae, 0xdd, 0xdb, 0x91, - 0xcc, 0x38, 0xb3, 0xad, 0x10, 0x84, 0xb8, 0x45, 0x36, 0xf3, 0x96, - 0xb4, 0xef, 0xba, 0xda, 0x10, 0xf8, 0x8b, 0xf3, 0xda +static const uint8_t kAESGCMCiphertext_128[64 + 16] = { + 0x38, 0x71, 0xcb, 0x61, 0x70, 0x60, 0x13, 0x8b, 0x2f, 0x91, 0x09, 0x7f, + 0x83, 0x20, 0x0f, 0x1f, 0x71, 0xe2, 0x47, 0x46, 0x6f, 0x5f, 0xa8, 0xad, + 0xa8, 0xfc, 0x0a, 0xfd, 0x36, 0x65, 0x84, 0x90, 0x28, 0x2b, 0xcb, 0x4f, + 0x68, 0xae, 0x09, 0xba, 0xae, 0xdd, 0xdb, 0x91, 0xcc, 0x38, 0xb3, 0xad, + 0x10, 0x84, 0xb8, 0x45, 0x36, 0xf3, 0x96, 0xb4, 0xef, 0xba, 0xda, 0x10, + 0xf8, 0x8b, 0xf3, 0xda, 0x91, 0x1f, 0x8c, 0xd8, 0x39, 0x7b, 0x1c, 0xfd, + 0xe7, 0x99, 0x7d, 0xb7, 0x22, 0x69, 0x67, 0xbd, }; -static const uint8_t kAESGCMCiphertext_192[64] = { - 0x05, 0x63, 0x6e, 0xe4, 0xd1, 0x9f, 0xd0, 0x91, 0x18, 0xc9, 0xf8, - 0xfd, 0xc2, 0x62, 0x09, 0x05, 0x91, 0xb4, 0x92, 0x66, 0x18, 0xe7, - 0x93, 0x6a, 0xc7, 0xde, 0x81, 0x36, 0x93, 0x79, 0x45, 0x34, 0xc0, - 0x6d, 0x14, 0x94, 0x93, 0x39, 0x2b, 0x7f, 0x4f, 0x10, 0x1c, 0xa5, - 0xfe, 0x3b, 0x37, 0xd7, 0x0a, 0x98, 0xd7, 0xb5, 0xe0, 0xdc, 0xe4, - 0x9f, 0x36, 0x40, 0xad, 0x03, 0xbf, 0x53, 0xe0, 0x7c +static const uint8_t kAESGCMCiphertext_192[64 + 16] = { + 0x05, 0x63, 0x6e, 0xe4, 0xd1, 0x9f, 0xd0, 0x91, 0x18, 0xc9, 0xf8, 0xfd, + 0xc2, 0x62, 0x09, 0x05, 0x91, 0xb4, 0x92, 0x66, 0x18, 0xe7, 0x93, 0x6a, + 0xc7, 0xde, 0x81, 0x36, 0x93, 0x79, 0x45, 0x34, 0xc0, 0x6d, 0x14, 0x94, + 0x93, 0x39, 0x2b, 0x7f, 0x4f, 0x10, 0x1c, 0xa5, 0xfe, 0x3b, 0x37, 0xd7, + 0x0a, 0x98, 0xd7, 0xb5, 0xe0, 0xdc, 0xe4, 0x9f, 0x36, 0x40, 0xad, 0x03, + 0xbf, 0x53, 0xe0, 0x7c, 0x3f, 0x57, 0x4f, 0x80, 0x99, 0xe6, 0x90, 0x4e, + 0x59, 0x2e, 0xe0, 0x76, 0x53, 0x09, 0xc3, 0xd3, }; -static const uint8_t kAESGCMCiphertext_256[64] = { - 0x92, 0x5f, 0xae, 0x84, 0xe7, 0x40, 0xfa, 0x1e, 0xaf, 0x8f, 0x97, - 0x0e, 0x8e, 0xdd, 0x6a, 0x94, 0x22, 0xee, 0x4f, 0x70, 0x66, 0xbf, - 0xb1, 0x99, 0x05, 0xbd, 0xd0, 0xd7, 0x91, 0x54, 0xaf, 0xe1, 0x52, - 0xc9, 0x4e, 0x55, 0xa5, 0x23, 0x62, 0x8b, 0x23, 0x40, 0x90, 0x56, - 0xe0, 0x68, 0x63, 0xe5, 0x7e, 0x5b, 0xbe, 0x96, 0x7b, 0xc4, 0x16, - 0xf9, 0xbe, 0x18, 0x06, 0x79, 0x8f, 0x99, 0x35, 0xe3 +static const uint8_t kAESGCMCiphertext_256[64 + 16] = { + 0x92, 0x5f, 0xae, 0x84, 0xe7, 0x40, 0xfa, 0x1e, 0xaf, 0x8f, 0x97, 0x0e, + 0x8e, 0xdd, 0x6a, 0x94, 0x22, 0xee, 0x4f, 0x70, 0x66, 0xbf, 0xb1, 0x99, + 0x05, 0xbd, 0xd0, 0xd7, 0x91, 0x54, 0xaf, 0xe1, 0x52, 0xc9, 0x4e, 0x55, + 0xa5, 0x23, 0x62, 0x8b, 0x23, 0x40, 0x90, 0x56, 0xe0, 0x68, 0x63, 0xe5, + 0x7e, 0x5b, 0xbe, 0x96, 0x7b, 0xc4, 0x16, 0xf9, 0xbe, 0x18, 0x06, 0x79, + 0x8f, 0x99, 0x35, 0xe3, 0x2a, 0x82, 0xb5, 0x5e, 0x8a, 0x06, 0xbe, 0x99, + 0x57, 0xb1, 0x76, 0xe1, 0xc5, 0xaa, 0x82, 0xe7, }; -struct AEADTestVector { +static const struct AEADTestVector { const char* name; - const EVP_AEAD *cipher; + const EVP_AEAD *aead; const uint8_t *key; const int key_length; const uint8_t *expected_ciphertext; const int cipher_text_length; - const int expect_approved; + const FIPSStatus expect_approved; const bool test_repeat_nonce; -} nAEADTestVectors[] = { +} kAEADTestVectors[] = { // Internal IV usage of AES-GCM is approved. - { "AES-GCM 128-bit key internal iv test", EVP_aead_aes_128_gcm_randnonce(), - kAESKey, 16, nullptr, 0, AWSLC_APPROVED, false }, - { "AES-GCM 256-bit key internal iv test", EVP_aead_aes_256_gcm_randnonce(), - kAESKey_256, 32, nullptr, 0, AWSLC_APPROVED, false }, + { + "AES-GCM 128-bit key internal iv test", + EVP_aead_aes_128_gcm_randnonce(), + kAESKey, + sizeof(kAESKey), + nullptr, + 0, + AWSLC_APPROVED, + false, + }, + { + "AES-GCM 256-bit key internal iv test", + EVP_aead_aes_256_gcm_randnonce(), + kAESKey_256, + sizeof(kAESKey_256), + nullptr, + 0, + AWSLC_APPROVED, + false, + }, // External IV usage of AES-GCM is not approved unless used within a TLS // context. - { "Generic AES-GCM 128-bit key external iv test", EVP_aead_aes_128_gcm(), - kAESKey, 16, kAESGCMCiphertext_128, 64, AWSLC_NOT_APPROVED, false }, - { "Generic AES-GCM 192-bit key external iv test", EVP_aead_aes_192_gcm(), - kAESKey_192, 24, kAESGCMCiphertext_192, 64, AWSLC_NOT_APPROVED, false }, - { "Generic AES-GCM 256-bit key external iv test", EVP_aead_aes_256_gcm(), - kAESKey_256, 32, kAESGCMCiphertext_256, 64, AWSLC_NOT_APPROVED, false }, + { + "Generic AES-GCM 128-bit key external iv test", + EVP_aead_aes_128_gcm(), + kAESKey, + sizeof(kAESKey), + kAESGCMCiphertext_128, + sizeof(kAESGCMCiphertext_128), + AWSLC_NOT_APPROVED, + false, + }, + { + "Generic AES-GCM 192-bit key external iv test", + EVP_aead_aes_192_gcm(), + kAESKey_192, + 24, + kAESGCMCiphertext_192, + sizeof(kAESGCMCiphertext_192), + AWSLC_NOT_APPROVED, + false, + }, + { + "Generic AES-GCM 256-bit key external iv test", + EVP_aead_aes_256_gcm(), + kAESKey_256, + sizeof(kAESKey_256), + kAESGCMCiphertext_256, + sizeof(kAESGCMCiphertext_256), + AWSLC_NOT_APPROVED, + false, + }, // External IV usage of AEAD AES-GCM APIs specific for TLS is approved. - { "TLS1.2 AES-GCM 128-bit key external iv test", EVP_aead_aes_128_gcm_tls12(), - kAESKey, 16, kAESGCMCiphertext_128, 64, AWSLC_APPROVED, true }, - { "TLS1.2 AES-GCM 256-bit key external iv test", EVP_aead_aes_256_gcm_tls12(), - kAESKey_256, 32, kAESGCMCiphertext_256, 64, AWSLC_APPROVED, true }, - { "TLS1.3 AES-GCM 128-bit key external iv test", EVP_aead_aes_128_gcm_tls13(), - kAESKey, 16, kAESGCMCiphertext_128, 64, AWSLC_APPROVED, true }, - { "TLS1.3 AES-GCM 256-bit key external iv test", EVP_aead_aes_256_gcm_tls13(), - kAESKey_256, 32, kAESGCMCiphertext_256, 64, AWSLC_APPROVED, true }, + { + "TLS1.2 AES-GCM 128-bit key external iv test", + EVP_aead_aes_128_gcm_tls12(), + kAESKey, + sizeof(kAESKey), + kAESGCMCiphertext_128, + sizeof(kAESGCMCiphertext_128), + AWSLC_APPROVED, + true, + }, + { + "TLS1.2 AES-GCM 256-bit key external iv test", + EVP_aead_aes_256_gcm_tls12(), + kAESKey_256, + sizeof(kAESKey_256), + kAESGCMCiphertext_256, + sizeof(kAESGCMCiphertext_256), + AWSLC_APPROVED, + true, + }, + { + "TLS1.3 AES-GCM 128-bit key external iv test", + EVP_aead_aes_128_gcm_tls13(), + kAESKey, + sizeof(kAESKey), + kAESGCMCiphertext_128, + sizeof(kAESGCMCiphertext_128), + AWSLC_APPROVED, + true, + }, + { + "TLS1.3 AES-GCM 256-bit key external iv test", + EVP_aead_aes_256_gcm_tls13(), + kAESKey_256, + sizeof(kAESKey_256), + kAESGCMCiphertext_256, + sizeof(kAESGCMCiphertext_256), + AWSLC_APPROVED, + true, + }, // 128 bit keys with 32 bit tag lengths are approved for AES-CCM. - { "AES-CCM 128-bit key test", EVP_aead_aes_128_ccm_bluetooth(), - kAESKey, 16, kAESCCMCiphertext, 64, AWSLC_APPROVED, false }, + { + "AES-CCM 128-bit key test", + EVP_aead_aes_128_ccm_bluetooth(), + kAESKey, + sizeof(kAESKey), + kAESCCMCiphertext, + sizeof(kAESCCMCiphertext), + AWSLC_APPROVED, + false, + }, }; -class AEAD_ServiceIndicatorTest : public awslc::TestWithNoErrors {}; +class AEADServiceIndicatorTest : public TestWithNoErrors {}; -INSTANTIATE_TEST_SUITE_P(All, AEAD_ServiceIndicatorTest, testing::ValuesIn(nAEADTestVectors)); +INSTANTIATE_TEST_SUITE_P(All, AEADServiceIndicatorTest, + testing::ValuesIn(kAEADTestVectors)); -TEST_P(AEAD_ServiceIndicatorTest, EVP_AEAD) { - const AEADTestVector &aeadTestVector = GetParam(); +TEST_P(AEADServiceIndicatorTest, EVP_AEAD) { + const AEADTestVector &test = GetParam(); + SCOPED_TRACE(test.name); - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; bssl::ScopedEVP_AEAD_CTX aead_ctx; - std::vector plaintext(kPlaintext, kPlaintext + sizeof(kPlaintext)); - std::vector nonce(EVP_AEAD_MAX_NONCE_LENGTH, 0); + std::vector nonce(EVP_AEAD_nonce_length(test.aead), 0); std::vector encrypt_output(256); std::vector decrypt_output(256); size_t out_len; @@ -694,161 +618,358 @@ TEST_P(AEAD_ServiceIndicatorTest, EVP_AEAD) { // |EVP_AEAD_CTX_seal| and |EVP_AEAD_CTX_open| for approval at the end. // |EVP_AEAD_CTX_init| should not be approved because the function does not // indicate that a service has been fully completed yet. - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EVP_AEAD_CTX_init(aead_ctx.get(), aeadTestVector.cipher, - aeadTestVector.key, aeadTestVector.key_length, 0, nullptr))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EVP_AEAD_CTX_seal(aead_ctx.get(), - encrypt_output.data(), &out_len, encrypt_output.size(), nonce.data(), EVP_AEAD_nonce_length(aeadTestVector.cipher), - plaintext.data(), plaintext.size(), nullptr, 0))); - ASSERT_EQ(approved, aeadTestVector.expect_approved); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(EVP_AEAD_CTX_init(aead_ctx.get(), test.aead, test.key, + test.key_length, 0, nullptr))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(EVP_AEAD_CTX_seal(aead_ctx.get(), encrypt_output.data(), + &out_len, encrypt_output.size(), nonce.data(), + EVP_AEAD_nonce_length(test.aead), kPlaintext, + sizeof(kPlaintext), nullptr, 0))); + EXPECT_EQ(approved, test.expect_approved); encrypt_output.resize(out_len); - if(aeadTestVector.expected_ciphertext) { - ASSERT_TRUE(check_test(aeadTestVector.expected_ciphertext, encrypt_output.data(), - aeadTestVector.cipher_text_length, aeadTestVector.name)); + if (test.expected_ciphertext) { + EXPECT_EQ(Bytes(test.expected_ciphertext, test.cipher_text_length), + Bytes(encrypt_output)); } - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EVP_AEAD_CTX_open(aead_ctx.get(), - decrypt_output.data(), &out_len, decrypt_output.size(), nonce.data(), EVP_AEAD_nonce_length(aeadTestVector.cipher), - encrypt_output.data(), out_len, nullptr, 0))); - ASSERT_EQ(approved, aeadTestVector.expect_approved); + CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE( + EVP_AEAD_CTX_open(aead_ctx.get(), decrypt_output.data(),&out_len, + decrypt_output.size(), nonce.data(), nonce.size(), + encrypt_output.data(), out_len, nullptr, 0))); + // Decryption doesn't have nonce uniqueness requirements and so is always + // approved for approved key lengths. + EXPECT_EQ(approved, test.key_length != 24 ? AWSLC_APPROVED + : AWSLC_NOT_APPROVED); decrypt_output.resize(out_len); - ASSERT_TRUE(check_test(plaintext.data(), decrypt_output.data(), plaintext.size(), - aeadTestVector.name)); + EXPECT_EQ(Bytes(kPlaintext), Bytes(decrypt_output)); // Second call when encrypting using the same nonce for AES-GCM TLS specific // functions should fail and return |AWSLC_NOT_APPROVED|. - if(aeadTestVector.test_repeat_nonce) { - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_FALSE(EVP_AEAD_CTX_seal(aead_ctx.get(), - encrypt_output.data(), &out_len, encrypt_output.size(), nonce.data(), EVP_AEAD_nonce_length(aeadTestVector.cipher), - kPlaintext, sizeof(kPlaintext), nullptr, 0))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - ASSERT_EQ(ERR_GET_REASON(ERR_get_error()), CIPHER_R_INVALID_NONCE); + if (test.test_repeat_nonce) { + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_FALSE( + EVP_AEAD_CTX_seal(aead_ctx.get(), encrypt_output.data(), &out_len, + encrypt_output.size(), nonce.data(), nonce.size(), + kPlaintext, sizeof(kPlaintext), nullptr, 0))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + EXPECT_EQ(ERR_GET_REASON(ERR_get_error()), CIPHER_R_INVALID_NONCE); } } -struct CipherTestVector { +static const struct CipherTestVector { const EVP_CIPHER *cipher; const uint8_t *key; const int key_length; const uint8_t *expected_ciphertext; const int cipher_text_length; const bool has_iv; - const int expect_approved; -} nTestVectors[] = { - { EVP_aes_128_ecb(), kAESKey, 16, kAESECBCiphertext, 64, false, AWSLC_APPROVED }, - { EVP_aes_192_ecb(), kAESKey_192, 24, kAESECBCiphertext_192, 64, false, AWSLC_APPROVED }, - { EVP_aes_256_ecb(), kAESKey_256, 32, kAESECBCiphertext_256, 64, false, AWSLC_APPROVED }, - { EVP_aes_128_cbc(), kAESKey, 16, kAESCBCCiphertext, 64, true, AWSLC_APPROVED }, - { EVP_aes_192_cbc(), kAESKey_192, 24, kAESCBCCiphertext_192, 64, true, AWSLC_APPROVED }, - { EVP_aes_256_cbc(), kAESKey_256, 32, kAESCBCCiphertext_256, 64, true, AWSLC_APPROVED }, - { EVP_aes_128_ctr(), kAESKey, 16, kAESCTRCiphertext, 64, true, AWSLC_APPROVED }, - { EVP_aes_192_ctr(), kAESKey_192, 24, kAESCTRCiphertext_192, 64, true, AWSLC_APPROVED }, - { EVP_aes_256_ctr(), kAESKey_256, 32, kAESCTRCiphertext_256, 64, true, AWSLC_APPROVED }, - { EVP_aes_128_ofb(), kAESKey, 16, kAESOFBCiphertext, 64, true, AWSLC_NOT_APPROVED }, - { EVP_des_ede3(), kAESKey_192, 24, KTDES_EDE3_CipherText, 64, false, AWSLC_NOT_APPROVED }, - { EVP_des_ede3_cbc(), kAESKey_192, 24, KTDES_EDE3_CBCCipherText, 64, false, AWSLC_NOT_APPROVED } + const FIPSStatus expect_approved; +} kTestVectors[] = { + { + EVP_aes_128_ecb(), + kAESKey, + sizeof(kAESKey), + kAESECBCiphertext, + sizeof(kAESECBCiphertext), + false, + AWSLC_APPROVED, + }, + { + EVP_aes_192_ecb(), + kAESKey_192, + sizeof(kAESKey_192), + kAESECBCiphertext_192, + sizeof(kAESECBCiphertext_192), + false, + AWSLC_APPROVED, + }, + { + EVP_aes_256_ecb(), + kAESKey_256, + sizeof(kAESKey_256), + kAESECBCiphertext_256, + sizeof(kAESECBCiphertext_256), + false, + AWSLC_APPROVED, + }, + { + EVP_aes_128_cbc(), + kAESKey, + sizeof(kAESKey), + kAESCBCCiphertext, + sizeof(kAESCBCCiphertext), + true, + AWSLC_APPROVED, + }, + { + EVP_aes_192_cbc(), + kAESKey_192, + sizeof(kAESKey_192), + kAESCBCCiphertext_192, + sizeof(kAESCBCCiphertext_192), + true, + AWSLC_APPROVED, + }, + { + EVP_aes_256_cbc(), + kAESKey_256, + sizeof(kAESKey_256), + kAESCBCCiphertext_256, + sizeof(kAESCBCCiphertext_256), + true, + AWSLC_APPROVED, + }, + { + EVP_aes_128_ctr(), + kAESKey, + sizeof(kAESKey), + kAESCTRCiphertext, + sizeof(kAESCTRCiphertext), + true, + AWSLC_APPROVED, + }, + { + EVP_aes_192_ctr(), + kAESKey_192, + sizeof(kAESKey_192), + kAESCTRCiphertext_192, + sizeof(kAESCTRCiphertext_192), + true, + AWSLC_APPROVED, + }, + { + EVP_aes_256_ctr(), + kAESKey_256, + sizeof(kAESKey_256), + kAESCTRCiphertext_256, + sizeof(kAESCTRCiphertext_256), + true, + AWSLC_APPROVED, + }, + { + EVP_aes_128_ofb(), + kAESKey, + sizeof(kAESKey), + kAESOFBCiphertext, + sizeof(kAESOFBCiphertext), + true, + AWSLC_NOT_APPROVED, + }, + { + EVP_des_ede3(), + kAESKey_192, + sizeof(kAESKey_192), + kTDES_EDE3_CipherText, + sizeof(kTDES_EDE3_CipherText), + false, + AWSLC_NOT_APPROVED, + }, + { + EVP_des_ede3_cbc(), + kAESKey_192, + sizeof(kAESKey_192), + kTDES_EDE3_CBCCipherText, + sizeof(kTDES_EDE3_CBCCipherText), + false, + AWSLC_NOT_APPROVED, + }, }; -class EVP_ServiceIndicatorTest : public awslc::TestWithNoErrors {}; +class EVPServiceIndicatorTest : public TestWithNoErrors {}; + +static void TestOperation(const EVP_CIPHER *cipher, bool encrypt, + const std::vector key, + const std::vector plaintext, + const std::vector ciphertext, + FIPSStatus expect_approved) { + FIPSStatus approved = AWSLC_NOT_APPROVED; + std::vector in, out; + if (encrypt) { + in = plaintext; + out = ciphertext; + } else { + in = ciphertext; + out = plaintext; + } + + bssl::ScopedEVP_CIPHER_CTX ctx; + // Test running the EVP_Cipher interfaces one by one directly, and check + // |EVP_EncryptFinal_ex| and |EVP_DecryptFinal_ex| for approval at the end. + ASSERT_TRUE(EVP_CipherInit_ex(ctx.get(), cipher, nullptr, nullptr, nullptr, + encrypt ? 1 : 0)); + ASSERT_LE(EVP_CIPHER_CTX_iv_length(ctx.get()), sizeof(kAESIV)); -INSTANTIATE_TEST_SUITE_P(All, EVP_ServiceIndicatorTest, testing::ValuesIn(nTestVectors)); + ASSERT_TRUE(EVP_CIPHER_CTX_set_key_length(ctx.get(), key.size())); + ASSERT_TRUE(EVP_CipherInit_ex(ctx.get(), cipher, nullptr, key.data(), kAESIV, + encrypt ? 1 : 0)); + ASSERT_TRUE(EVP_CIPHER_CTX_set_padding(ctx.get(), 0)); + std::vector encrypt_result; + DoCipherFinal(ctx.get(), &encrypt_result, in, expect_approved); + EXPECT_EQ(Bytes(out), Bytes(encrypt_result)); -TEST_P(EVP_ServiceIndicatorTest, EVP_Ciphers) { - const CipherTestVector &evpTestVector = GetParam(); + // Test using the one-shot |EVP_Cipher| function for approval. + bssl::ScopedEVP_CIPHER_CTX ctx2; + uint8_t output[256]; + ASSERT_TRUE(EVP_CipherInit_ex(ctx2.get(), cipher, nullptr, key.data(), kAESIV, + encrypt ? 1 : 0)); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, EVP_Cipher(ctx2.get(), output, in.data(), in.size())); + EXPECT_EQ(approved, expect_approved); + EXPECT_EQ(Bytes(out), Bytes(output, in.size())); +} - const EVP_CIPHER *cipher = evpTestVector.cipher; - std::vector key(evpTestVector.key, evpTestVector.key + evpTestVector.key_length); - std::vector plaintext(kPlaintext, kPlaintext + sizeof(kPlaintext)); - std::vector ciphertext(evpTestVector.expected_ciphertext, evpTestVector.expected_ciphertext + evpTestVector.cipher_text_length); +INSTANTIATE_TEST_SUITE_P(All, EVPServiceIndicatorTest, + testing::ValuesIn(kTestVectors)); - TestOperation(cipher, true /* encrypt */, key, plaintext, ciphertext, evpTestVector.expect_approved); - TestOperation(cipher, false /* decrypt */, key, plaintext, ciphertext, evpTestVector.expect_approved); +TEST_P(EVPServiceIndicatorTest, EVP_Ciphers) { + const CipherTestVector &test = GetParam(); + + const EVP_CIPHER *cipher = test.cipher; + std::vector key(test.key, test.key + test.key_length); + std::vector plaintext(kPlaintext, kPlaintext + sizeof(kPlaintext)); + std::vector ciphertext( + test.expected_ciphertext, + test.expected_ciphertext + test.cipher_text_length); + + TestOperation(cipher, true /* encrypt */, key, plaintext, ciphertext, + test.expect_approved); + TestOperation(cipher, false /* decrypt */, key, plaintext, ciphertext, + test.expect_approved); } -struct MD { +static const struct DigestTestVector { // name is the name of the digest test. - const char* name; + const char *name; // length of digest. const int length; // func is the digest to test. const EVP_MD *(*func)(); // one_shot_func is the convenience one-shot version of the digest. uint8_t *(*one_shot_func)(const uint8_t *, size_t, uint8_t *); -}; - -static const MD md4 = { "KAT for MD4", MD4_DIGEST_LENGTH, &EVP_md4, &MD4 }; -static const MD md5 = { "KAT for MD5", MD5_DIGEST_LENGTH, &EVP_md5, &MD5 }; -static const MD sha1 = { "KAT for SHA1", SHA_DIGEST_LENGTH, &EVP_sha1, &SHA1 }; -static const MD sha224 = { "KAT for SHA224", SHA224_DIGEST_LENGTH, &EVP_sha224, &SHA224 }; -static const MD sha256 = { "KAT for SHA256", SHA256_DIGEST_LENGTH, &EVP_sha256, &SHA256 }; -static const MD sha384 = { "KAT for SHA384", SHA384_DIGEST_LENGTH, &EVP_sha384, &SHA384 }; -static const MD sha512 = { "KAT for SHA512", SHA512_DIGEST_LENGTH, &EVP_sha512, &SHA512 }; -static const MD sha512_256 = { "KAT for SHA512-256", SHA512_256_DIGEST_LENGTH, &EVP_sha512_256, &SHA512_256 }; - -struct DigestTestVector { - // md is the digest to test. - const MD &md; // expected_digest is the expected digest. const uint8_t *expected_digest; // expected to be approved or not. - const int expect_approved; + const FIPSStatus expect_approved; } kDigestTestVectors[] = { - { md4, kOutput_md4, AWSLC_NOT_APPROVED }, - { md5, kOutput_md5, AWSLC_NOT_APPROVED }, - { sha1, kOutput_sha1, AWSLC_APPROVED }, - { sha224, kOutput_sha224, AWSLC_APPROVED }, - { sha256, kOutput_sha256, AWSLC_APPROVED }, - { sha384, kOutput_sha384, AWSLC_APPROVED }, - { sha512, kOutput_sha512, AWSLC_APPROVED }, - { sha512_256, kOutput_sha512_256, AWSLC_APPROVED } + { + "MD4", + MD4_DIGEST_LENGTH, + &EVP_md4, + &MD4, + kOutput_md4, + AWSLC_NOT_APPROVED, + }, + { + "MD5", + MD5_DIGEST_LENGTH, + &EVP_md5, + &MD5, + kOutput_md5, + AWSLC_NOT_APPROVED, + }, + { + "SHA-1", + SHA_DIGEST_LENGTH, + &EVP_sha1, + &SHA1, + kOutput_sha1, + AWSLC_APPROVED, + }, + { + "SHA-224", + SHA224_DIGEST_LENGTH, + &EVP_sha224, + &SHA224, + kOutput_sha224, + AWSLC_APPROVED, + }, + { + "SHA-256", + SHA256_DIGEST_LENGTH, + &EVP_sha256, + &SHA256, + kOutput_sha256, + AWSLC_APPROVED, + }, + { + "SHA-384", + SHA384_DIGEST_LENGTH, + &EVP_sha384, + &SHA384, + kOutput_sha384, + AWSLC_APPROVED, + }, + { + "SHA-512", + SHA512_DIGEST_LENGTH, + &EVP_sha512, + &SHA512, + kOutput_sha512, + AWSLC_APPROVED, + }, + { + "SHA-512/256", + SHA512_256_DIGEST_LENGTH, + &EVP_sha512_256, + &SHA512_256, + kOutput_sha512_256, + AWSLC_APPROVED, + }, }; -class EVP_MD_ServiceIndicatorTest : public awslc::TestWithNoErrors {}; +class EVPMDServiceIndicatorTest : public TestWithNoErrors {}; -INSTANTIATE_TEST_SUITE_P(All, EVP_MD_ServiceIndicatorTest, testing::ValuesIn(kDigestTestVectors)); +INSTANTIATE_TEST_SUITE_P(All, EVPMDServiceIndicatorTest, + testing::ValuesIn(kDigestTestVectors)); -TEST_P(EVP_MD_ServiceIndicatorTest, EVP_Digests) { - const DigestTestVector &digestTestVector = GetParam(); +TEST_P(EVPMDServiceIndicatorTest, EVP_Digests) { + const DigestTestVector &test = GetParam(); + SCOPED_TRACE(test.name); - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; bssl::ScopedEVP_MD_CTX ctx; - std::vector plaintext(kPlaintext, kPlaintext + sizeof(kPlaintext)); - std::vector digest(digestTestVector.md.length); + std::vector digest(test.length); unsigned digest_len; // Test running the EVP_Digest interfaces one by one directly, and check // |EVP_DigestFinal_ex| for approval at the end. |EVP_DigestInit_ex| and // |EVP_DigestUpdate| should not be approved, because the functions do not // indicate that a service has been fully completed yet. - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EVP_DigestInit_ex(ctx.get(), digestTestVector.md.func(), nullptr))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EVP_DigestUpdate(ctx.get(), plaintext.data(), plaintext.size()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EVP_DigestFinal_ex(ctx.get(), digest.data(), &digest_len))); - ASSERT_EQ(approved, digestTestVector.expect_approved); - ASSERT_TRUE(check_test(digestTestVector.expected_digest, digest.data(), digest_len, digestTestVector.md.name)); - + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(EVP_DigestInit_ex(ctx.get(), test.func(), nullptr))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(EVP_DigestUpdate(ctx.get(), kPlaintext, sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(EVP_DigestFinal_ex(ctx.get(), digest.data(), &digest_len))); + EXPECT_EQ(approved, test.expect_approved); + EXPECT_EQ(Bytes(test.expected_digest, digest_len), Bytes(digest)); // Test using the one-shot |EVP_Digest| function for approval. - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EVP_Digest(plaintext.data(), plaintext.size(), - digest.data(), &digest_len, digestTestVector.md.func(), nullptr))); - ASSERT_EQ(approved, digestTestVector.expect_approved); - ASSERT_TRUE(check_test(digestTestVector.expected_digest, digest.data(), digest_len, digestTestVector.md.name)); - + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(EVP_Digest(kPlaintext, sizeof(kPlaintext), digest.data(), + &digest_len, test.func(), nullptr))); + EXPECT_EQ(approved, test.expect_approved); + EXPECT_EQ(Bytes(test.expected_digest, test.length), Bytes(digest)); // Test using the one-shot API for approval. - CALL_SERVICE_AND_CHECK_APPROVED(approved, digestTestVector.md.one_shot_func(plaintext.data(), plaintext.size(), digest.data())); - ASSERT_EQ(approved, digestTestVector.expect_approved); - ASSERT_TRUE(check_test(digestTestVector.expected_digest, digest.data(), digestTestVector.md.length, digestTestVector.md.name)); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, + test.one_shot_func(kPlaintext, sizeof(kPlaintext), digest.data())); + EXPECT_EQ(approved, test.expect_approved); + EXPECT_EQ(Bytes(test.expected_digest, test.length), Bytes(digest)); } -struct HMACTestVector { +static const struct HMACTestVector { // func is the hash function for HMAC to test. const EVP_MD *(*func)(void); // expected_digest is the expected digest. const uint8_t *expected_digest; // expected to be approved or not. - const int expect_approved; + const FIPSStatus expect_approved; } kHMACTestVectors[] = { { EVP_sha1, kHMACOutput_sha1, AWSLC_APPROVED }, { EVP_sha224, kHMACOutput_sha224, AWSLC_APPROVED }, @@ -858,19 +979,21 @@ struct HMACTestVector { { EVP_sha512_256, kHMACOutput_sha512_256, AWSLC_NOT_APPROVED } }; -class HMAC_ServiceIndicatorTest : public awslc::TestWithNoErrors {}; +class HMACServiceIndicatorTest : public TestWithNoErrors {}; -INSTANTIATE_TEST_SUITE_P(All, HMAC_ServiceIndicatorTest, testing::ValuesIn(kHMACTestVectors)); +INSTANTIATE_TEST_SUITE_P(All, HMACServiceIndicatorTest, + testing::ValuesIn(kHMACTestVectors)); -TEST_P(HMAC_ServiceIndicatorTest, HMACTest) { - const HMACTestVector &hmacTestVector = GetParam(); +TEST_P(HMACServiceIndicatorTest, HMACTest) { + const HMACTestVector &test = GetParam(); - int approved = AWSLC_NOT_APPROVED; - const uint8_t kHMACKey[64] = {0}; - const EVP_MD *digest = hmacTestVector.func(); - std::vector plaintext(kPlaintext, kPlaintext + sizeof(kPlaintext)); - std::vector key(kHMACKey, kHMACKey + sizeof(kHMACKey)); - unsigned expected_mac_len = EVP_MD_size(digest); + FIPSStatus approved = AWSLC_NOT_APPROVED; + // The key is deliberately long in order to trigger digesting it down to a + // block size. This tests that doing so does not cause the indicator to be + // mistakenly set in |HMAC_Init_ex|. + const uint8_t kHMACKey[512] = {0}; + const EVP_MD *const digest = test.func(); + const unsigned expected_mac_len = EVP_MD_size(digest); std::vector mac(expected_mac_len); // Test running the HMAC interfaces one by one directly, and check @@ -879,86 +1002,94 @@ TEST_P(HMAC_ServiceIndicatorTest, HMACTest) { // service has been fully completed yet. unsigned mac_len; bssl::ScopedHMAC_CTX ctx; - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(HMAC_Init_ex(ctx.get(), key.data(), key.size(), digest, nullptr))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(HMAC_Update(ctx.get(), plaintext.data(), plaintext.size()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(HMAC_Final(ctx.get(), mac.data(), &mac_len))); - ASSERT_EQ(approved, hmacTestVector.expect_approved); - ASSERT_TRUE(check_test(hmacTestVector.expected_digest, mac.data(), mac_len, "HMAC KAT")); - + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE( + HMAC_Init_ex(ctx.get(), kHMACKey, sizeof(kHMACKey), digest, nullptr))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(HMAC_Update(ctx.get(), kPlaintext, sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(HMAC_Final(ctx.get(), mac.data(), &mac_len))); + EXPECT_EQ(approved, test.expect_approved); + EXPECT_EQ(Bytes(test.expected_digest, expected_mac_len), + Bytes(mac.data(), mac_len)); // Test using the one-shot API for approval. - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(HMAC(digest, key.data(), - key.size(), plaintext.data(), plaintext.size(), mac.data(), &mac_len))); - ASSERT_EQ(approved, hmacTestVector.expect_approved); - ASSERT_TRUE(check_test(hmacTestVector.expected_digest, mac.data(), mac_len, "HMAC KAT")); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(HMAC(digest, kHMACKey, sizeof(kHMACKey), kPlaintext, + sizeof(kPlaintext), mac.data(), &mac_len))); + EXPECT_EQ(approved, test.expect_approved); + EXPECT_EQ(Bytes(test.expected_digest, expected_mac_len), + Bytes(mac.data(), mac_len)); } // RSA tests are not parameterized with the |kRSATestVectors| as key // generation for RSA is time consuming. TEST(ServiceIndicatorTest, RSAKeyGen) { - int approved = AWSLC_NOT_APPROVED; - bssl::UniquePtr rsa(RSA_new()); - ASSERT_TRUE(rsa); + FIPSStatus approved = AWSLC_NOT_APPROVED; + bssl::UniquePtr rsa(RSA_new()); + ASSERT_TRUE(rsa); - // |RSA_generate_key_fips| may only be used for 2048-, 3072-, and 4096-bit - // keys. - for (const size_t bits : {512, 1024, 3071, 4095}) { - SCOPED_TRACE(bits); + // |RSA_generate_key_fips| may only be used for 2048-, 3072-, and 4096-bit + // keys. + for (const size_t bits : {512, 1024, 3071, 4095}) { + SCOPED_TRACE(bits); - rsa.reset(RSA_new()); - CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_FALSE(RSA_generate_key_fips(rsa.get(), bits, nullptr))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - } + rsa.reset(RSA_new()); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), bits, nullptr))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + } - // Test that we can generate keys of the supported lengths: - for (const size_t bits : {2048, 3072, 4096}) { - SCOPED_TRACE(bits); + // Test that we can generate keys of the supported lengths: + for (const size_t bits : {2048, 3072, 4096}) { + SCOPED_TRACE(bits); - rsa.reset(RSA_new()); - CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(RSA_generate_key_fips(rsa.get(), bits, nullptr))); - ASSERT_EQ(approved, AWSLC_APPROVED); - ASSERT_EQ(bits, BN_num_bits(rsa->n)); - } + rsa.reset(RSA_new()); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + EXPECT_TRUE( RSA_generate_key_fips(rsa.get(), bits, nullptr))); + EXPECT_EQ(approved, AWSLC_APPROVED); + EXPECT_EQ(bits, BN_num_bits(rsa->n)); + } // Test running the EVP_PKEY_keygen interfaces one by one directly, and check // |EVP_PKEY_keygen| for approval at the end. |EVP_PKEY_keygen_init| should // not be approved because it does not indicate an entire service has been - // done. + // completed. bssl::UniquePtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr)); EVP_PKEY *raw = nullptr; bssl::UniquePtr pkey(raw); ASSERT_TRUE(ctx); - // Test unapproved key sizes of RSA. - for(const size_t bits : {512, 1024, 3071, 4095}) { - SCOPED_TRACE(bits); - CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), bits)); - CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_FALSE(EVP_PKEY_keygen(ctx.get(), &raw))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - // Prevent memory leakage. - pkey.reset(raw); - raw = nullptr; - } - // Test approved key sizes of RSA. - for(const size_t bits : {2048, 3072, 4096}) { - SCOPED_TRACE(bits); - CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), bits)); - CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw))); - ASSERT_EQ(approved, AWSLC_APPROVED); - // Prevent memory leakage. - pkey.reset(raw); - raw = nullptr; + + if (kEVPKeyGenShouldCallFIPSFunctions) { + // Test unapproved key sizes of RSA. + for (const size_t bits : {512, 1024, 3071, 4095}) { + SCOPED_TRACE(bits); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), bits)); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_FALSE(EVP_PKEY_keygen(ctx.get(), &raw))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + pkey.reset(raw); + raw = nullptr; + } + + // Test approved key sizes of RSA. + for (const size_t bits : {2048, 3072, 4096}) { + SCOPED_TRACE(bits); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), bits)); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw))); + EXPECT_EQ(approved, AWSLC_APPROVED); + pkey.reset(raw); + raw = nullptr; + } } } @@ -970,14 +1101,14 @@ struct RSATestVector { // whether to use pss testing or not. const bool use_pss; // expected to be approved or not for signature generation. - const int sig_gen_expect_approved; + const FIPSStatus sig_gen_expect_approved; // expected to be approved or not for signature verification. - const int sig_ver_expect_approved; + const FIPSStatus sig_ver_expect_approved; }; struct RSATestVector kRSATestVectors[] = { // RSA test cases that are not approved in any case. { 512, &EVP_sha1, false, AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED }, - { 512, &EVP_sha256, true, AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED }, + // PSS with hashLen == saltLen is not possible for 512-bit modulus. { 1024, &EVP_md5, false, AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED }, { 1536, &EVP_sha256, false, AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED }, { 1536, &EVP_sha512, true, AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED }, @@ -993,7 +1124,8 @@ struct RSATestVector kRSATestVectors[] = { { 1024, &EVP_sha512, false, AWSLC_NOT_APPROVED, AWSLC_APPROVED }, { 1024, &EVP_sha1, true, AWSLC_NOT_APPROVED, AWSLC_APPROVED }, { 1024, &EVP_sha256, true, AWSLC_NOT_APPROVED, AWSLC_APPROVED }, - { 1024, &EVP_sha512, true, AWSLC_NOT_APPROVED, AWSLC_APPROVED }, + // PSS with hashLen == saltLen is not possible for 1024-bit modulus and + // SHA-512. { 2048, &EVP_sha1, false, AWSLC_NOT_APPROVED, AWSLC_APPROVED }, { 2048, &EVP_sha224, false, AWSLC_APPROVED, AWSLC_APPROVED }, @@ -1029,105 +1161,166 @@ struct RSATestVector kRSATestVectors[] = { { 4096, &EVP_sha512, true, AWSLC_APPROVED, AWSLC_APPROVED }, }; -class RSA_ServiceIndicatorTest : public awslc::TestWithNoErrors {}; +class RSAServiceIndicatorTest : public TestWithNoErrors {}; + +INSTANTIATE_TEST_SUITE_P(All, RSAServiceIndicatorTest, + testing::ValuesIn(kRSATestVectors)); + +static std::map> &CachedRSAKeys() { + static std::map> keys; + return keys; +} + + +static RSA *GetRSAKey(unsigned bits) { + auto it = CachedRSAKeys().find(bits); + if (it != CachedRSAKeys().end()) { + return it->second.get(); + } + + bssl::UniquePtr e(BN_new()); + if (!e || !BN_set_word(e.get(), RSA_F4)) { + abort(); + } -INSTANTIATE_TEST_SUITE_P(All, RSA_ServiceIndicatorTest, testing::ValuesIn(kRSATestVectors)); + bssl::UniquePtr key(RSA_new()); + if (!key || !RSA_generate_key_ex(key.get(), bits, e.get(), nullptr)) { + abort(); + } -TEST_P(RSA_ServiceIndicatorTest, RSASigGen) { - const RSATestVector &rsaTestVector = GetParam(); + RSA *const ret = key.get(); + CachedRSAKeys().emplace(static_cast(bits), std::move(key)); + return ret; +} - int approved = AWSLC_NOT_APPROVED; - RSA *rsa = RSA_new(); +// When using |EVP_PKEY_assign| to assign |RSA| to |EVP_PKEY|, the pointer will +// get assigned to |EVP_PKEY| and get freed along with it. +static RSA *GetRSAPSSKey(unsigned bits) { bssl::UniquePtr e(BN_new()); + if (!e || !BN_set_word(e.get(), RSA_F4)) { + abort(); + } + + RSA *key = RSA_new(); + if (!key || !RSA_generate_key_ex(key, bits, e.get(), nullptr)) { + abort(); + } + + return key; +} + +TEST_P(RSAServiceIndicatorTest, RSASigGen) { + const RSATestVector &test = GetParam(); + SCOPED_TRACE(test.key_size); + bssl::UniquePtr pkey(EVP_PKEY_new()); - bssl::ScopedEVP_MD_CTX md_ctx; - EVP_PKEY_CTX *pctx; ASSERT_TRUE(pkey); - ASSERT_TRUE(rsa); - BN_set_word(e.get(), RSA_F4); - - // Generate a generic rsa key. - ASSERT_TRUE(RSA_generate_key_ex(rsa, rsaTestVector.key_size, e.get(), nullptr)); - if(rsaTestVector.use_pss) { + RSA *rsa = nullptr; + if(test.use_pss) { + rsa = GetRSAPSSKey(test.key_size); ASSERT_TRUE(EVP_PKEY_assign(pkey.get(), EVP_PKEY_RSA_PSS, rsa)); } else { - ASSERT_TRUE(EVP_PKEY_assign_RSA(pkey.get(), rsa)); - } + rsa = GetRSAKey(test.key_size); + ASSERT_TRUE(EVP_PKEY_set1_RSA(pkey.get(), rsa)); + } // Test running the EVP_DigestSign interfaces one by one directly, and check - // |EVP_DigestSignFinal| for approval at the end. |EVP_DigestSignInit|, + // |EVP_DigestSignFinal| for approval at the end. |EVP_DigestSignInit|, and // |EVP_DigestSignUpdate| should not be approved because they do not indicate - // an entire service has been done. - std::vector final_output; + // an entire service has been completed. + FIPSStatus approved = AWSLC_NOT_APPROVED; + bssl::ScopedEVP_MD_CTX md_ctx; + EVP_PKEY_CTX *pctx = nullptr; size_t sig_len; CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), &pctx, rsaTestVector.func(), nullptr, pkey.get()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - if(rsaTestVector.use_pss) { + ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), &pctx, test.func(), + nullptr, pkey.get()))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + if (test.use_pss) { CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); } - CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestSignUpdate(md_ctx.get(), kPlaintext, sizeof(kPlaintext)))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - // Determine the size of the signature. The first call of |EVP_DigestSignFinal| - // should not return an approval check because no crypto is being done when - // |nullptr| is inputted in the |*out_sig| field. - CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), nullptr, &sig_len))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - final_output.resize(sig_len); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(EVP_DigestSignUpdate(md_ctx.get(), kPlaintext, + sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + // Determine the size of the signature. The first call of + // |EVP_DigestSignFinal| should not return an approval check because no crypto + // is being done when |nullptr| is inputted in the |*out_sig| field. + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), nullptr, + &sig_len))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + std::vector signature(sig_len); // The second call performs the actual operation. - CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), final_output.data(), &sig_len))); - ASSERT_EQ(approved, rsaTestVector.sig_gen_expect_approved); - + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), signature.data(), + &sig_len))); + EXPECT_EQ(approved, test.sig_gen_expect_approved); // Test using the one-shot |EVP_DigestSign| function for approval. md_ctx.Reset(); std::vector oneshot_output(sig_len); - CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), &pctx, rsaTestVector.func(), nullptr, pkey.get()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - if(rsaTestVector.use_pss) { - CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), &pctx, test.func(), + nullptr, pkey.get()))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + if (test.use_pss) { + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); } CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), oneshot_output.data(), &sig_len, kPlaintext, sizeof(kPlaintext)))); - ASSERT_EQ(approved, rsaTestVector.sig_gen_expect_approved); + EXPECT_EQ(approved, test.sig_gen_expect_approved); + + if (test.use_pss) { + // Odd configurations of PSS, for example where the salt length is not equal + // to the hash length, are not approved. + md_ctx.Reset(); + ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), &pctx, test.func(), nullptr, + pkey.get())); + ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING)); + ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, 10)); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), oneshot_output.data(), + &sig_len, kPlaintext, sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + } } -TEST_P(RSA_ServiceIndicatorTest, RSASigVer) { - const RSATestVector &rsaTestVector = GetParam(); +TEST_P(RSAServiceIndicatorTest, RSASigVer) { + const RSATestVector &test = GetParam(); - int approved = AWSLC_NOT_APPROVED; - - RSA *rsa = RSA_new(); - bssl::UniquePtr e(BN_new()); bssl::UniquePtr pkey(EVP_PKEY_new()); - bssl::ScopedEVP_MD_CTX md_ctx; - EVP_PKEY_CTX *pctx; ASSERT_TRUE(pkey); - ASSERT_TRUE(rsa); - BN_set_word(e.get(), RSA_F4); - // Generate a generic rsa key. - ASSERT_TRUE(RSA_generate_key_ex(rsa, rsaTestVector.key_size, e.get(), nullptr)); - if(rsaTestVector.use_pss) { + RSA *rsa = nullptr; + if(test.use_pss) { + rsa = GetRSAPSSKey(test.key_size); ASSERT_TRUE(EVP_PKEY_assign(pkey.get(), EVP_PKEY_RSA_PSS, rsa)); } else { - ASSERT_TRUE(EVP_PKEY_assign_RSA(pkey.get(), rsa)); - } + rsa = GetRSAKey(test.key_size); + ASSERT_TRUE(EVP_PKEY_set1_RSA(pkey.get(), rsa)); + } std::vector signature; size_t sig_len; - ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), &pctx, rsaTestVector.func(), nullptr, pkey.get())); - if(rsaTestVector.use_pss) { + bssl::ScopedEVP_MD_CTX md_ctx; + EVP_PKEY_CTX *pctx = nullptr; + ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), &pctx, test.func(), nullptr, + pkey.get())); + if (test.use_pss) { ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING)); + ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1)); } ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), nullptr, &sig_len, nullptr, 0)); signature.resize(sig_len); @@ -1139,91 +1332,103 @@ TEST_P(RSA_ServiceIndicatorTest, RSASigVer) { // Test running the EVP_DigestVerify interfaces one by one directly, and check // |EVP_DigestVerifyFinal| for approval at the end. |EVP_DigestVerifyInit|, - // |EVP_DigestVerifyUpdate| should not be approved because they do not indicate - // an entire service has been done. + // |EVP_DigestVerifyUpdate| should not be approved because they do not + // indicate an entire service has been done. + FIPSStatus approved = AWSLC_NOT_APPROVED; md_ctx.Reset(); CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx.get(), &pctx, rsaTestVector.func(), nullptr, pkey.get()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - if(rsaTestVector.use_pss) { + ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx.get(), &pctx, test.func(), + nullptr, pkey.get()))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + if (test.use_pss) { CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1)); } CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestVerifyUpdate(md_ctx.get(), kPlaintext, sizeof(kPlaintext)))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + ASSERT_TRUE(EVP_DigestVerifyUpdate(md_ctx.get(), kPlaintext, + sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestVerifyFinal(md_ctx.get(), signature.data(), signature.size()))); - ASSERT_EQ(approved, rsaTestVector.sig_ver_expect_approved); + ASSERT_TRUE(EVP_DigestVerifyFinal(md_ctx.get(), signature.data(), + signature.size()))); + EXPECT_EQ(approved, test.sig_ver_expect_approved); // Test using the one-shot |EVP_DigestVerify| function for approval. md_ctx.Reset(); CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx.get(), &pctx, rsaTestVector.func(), nullptr, pkey.get()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - if(rsaTestVector.use_pss) { + ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx.get(), &pctx, test.func(), + nullptr, pkey.get()))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + if (test.use_pss) { CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1)); } CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestVerify(md_ctx.get(), signature.data(), - signature.size(), kPlaintext, - sizeof(kPlaintext)))); - ASSERT_EQ(approved, rsaTestVector.sig_ver_expect_approved); + ASSERT_TRUE(EVP_DigestVerify(md_ctx.get(), signature.data(), + signature.size(), kPlaintext, + sizeof(kPlaintext)))); + EXPECT_EQ(approved, test.sig_ver_expect_approved); } // Test that |EVP_DigestSignFinal| and |EVP_DigestSignVerify| are approved with // manually constructing using the context setting functions. -TEST_P(RSA_ServiceIndicatorTest, ManualRSASignVerify) { - const RSATestVector &rsaTestVector = GetParam(); +// AWS-LC uses this to test support of the function |EVP_MD_CTX_set_pkey_ctx|. +TEST_P(RSAServiceIndicatorTest, ManualRSASignVerify) { + const RSATestVector &test = GetParam(); - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; - bssl::ScopedEVP_MD_CTX ctx; - ASSERT_TRUE(EVP_DigestInit(ctx.get(), rsaTestVector.func())); - ASSERT_TRUE(EVP_DigestUpdate(ctx.get(), kPlaintext, sizeof(kPlaintext))); - - RSA *rsa = RSA_new(); - bssl::UniquePtr e(BN_new()); bssl::UniquePtr pkey(EVP_PKEY_new()); - BN_set_word(e.get(), RSA_F4); + ASSERT_TRUE(pkey); - // Generate a generic rsa key. - ASSERT_TRUE(RSA_generate_key_ex(rsa, rsaTestVector.key_size, e.get(), nullptr)); - if(rsaTestVector.use_pss) { + RSA *rsa = nullptr; + if(test.use_pss) { + rsa = GetRSAPSSKey(test.key_size); ASSERT_TRUE(EVP_PKEY_assign(pkey.get(), EVP_PKEY_RSA_PSS, rsa)); } else { - ASSERT_TRUE(EVP_PKEY_assign_RSA(pkey.get(), rsa)); - } + rsa = GetRSAKey(test.key_size); + ASSERT_TRUE(EVP_PKEY_set1_RSA(pkey.get(), rsa)); + } + + bssl::ScopedEVP_MD_CTX ctx; + ASSERT_TRUE(EVP_DigestInit(ctx.get(), test.func())); + ASSERT_TRUE(EVP_DigestUpdate(ctx.get(), kPlaintext, sizeof(kPlaintext))); // Manual construction for signing. bssl::UniquePtr pctx(EVP_PKEY_CTX_new(pkey.get(), nullptr)); ASSERT_TRUE(EVP_PKEY_sign_init(pctx.get())); - ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(pctx.get(), rsaTestVector.func())); + ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(pctx.get(), test.func())); + if (test.use_pss) { + ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pctx.get(), + RSA_PKCS1_PSS_PADDING)); + ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx.get(), -1)); + } EVP_MD_CTX_set_pkey_ctx(ctx.get(), pctx.get()); // Determine the size of the signature. size_t sig_len = 0; CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestSignFinal(ctx.get(), nullptr, &sig_len))); + ASSERT_TRUE(EVP_DigestSignFinal(ctx.get(), nullptr, &sig_len))); ASSERT_EQ(approved, AWSLC_NOT_APPROVED); std::vector sig; sig.resize(sig_len); CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestSignFinal(ctx.get(), sig.data(), &sig_len))); - ASSERT_EQ(approved, rsaTestVector.sig_gen_expect_approved); + EVP_DigestSignFinal(ctx.get(), sig.data(), &sig_len)); + ASSERT_EQ(approved, test.sig_gen_expect_approved); sig.resize(sig_len); // Manual construction for verification. ASSERT_TRUE(EVP_PKEY_verify_init(pctx.get())); - ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(pctx.get(), rsaTestVector.func())); + ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(pctx.get(), test.func())); EVP_MD_CTX_set_pkey_ctx(ctx.get(), pctx.get()); CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestVerifyFinal(ctx.get(), sig.data(), sig_len))); - ASSERT_EQ(approved, rsaTestVector.sig_ver_expect_approved); + EVP_DigestVerifyFinal(ctx.get(), sig.data(), sig_len)); + ASSERT_EQ(approved, test.sig_ver_expect_approved); } struct ECDSATestVector { @@ -1232,149 +1437,195 @@ struct ECDSATestVector { // md_func is the digest to test. const EVP_MD *(*func)(); // expected to be approved or not for signature generation. - const int key_check_expect_approved; + const FIPSStatus key_check_expect_approved; // expected to be approved or not for signature generation. - const int sig_gen_expect_approved; + const FIPSStatus sig_gen_expect_approved; // expected to be approved or not for signature verification. - const int sig_ver_expect_approved; + const FIPSStatus sig_ver_expect_approved; }; -struct ECDSATestVector kECDSATestVectors[] = { - // Only the following NIDs for |EC_GROUP| are creatable with - // |EC_GROUP_new_by_curve_name|. - { NID_secp224r1, &EVP_sha1, AWSLC_APPROVED, AWSLC_NOT_APPROVED, AWSLC_APPROVED }, - { NID_secp224r1, &EVP_sha224, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - { NID_secp224r1, &EVP_sha256, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - { NID_secp224r1, &EVP_sha384, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - { NID_secp224r1, &EVP_sha512, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - - { NID_X9_62_prime256v1, &EVP_sha1, AWSLC_APPROVED, AWSLC_NOT_APPROVED, AWSLC_APPROVED }, - { NID_X9_62_prime256v1, &EVP_sha224, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - { NID_X9_62_prime256v1, &EVP_sha256, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - { NID_X9_62_prime256v1, &EVP_sha384, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - { NID_X9_62_prime256v1, &EVP_sha512, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - - { NID_secp384r1, &EVP_sha1, AWSLC_APPROVED, AWSLC_NOT_APPROVED, AWSLC_APPROVED }, - { NID_secp384r1, &EVP_sha224, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - { NID_secp384r1, &EVP_sha256, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - { NID_secp384r1, &EVP_sha384, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - { NID_secp384r1, &EVP_sha512, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - - { NID_secp521r1, &EVP_sha1, AWSLC_APPROVED, AWSLC_NOT_APPROVED, AWSLC_APPROVED }, - { NID_secp521r1, &EVP_sha224, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - { NID_secp521r1, &EVP_sha256, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - { NID_secp521r1, &EVP_sha384, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - { NID_secp521r1, &EVP_sha512, AWSLC_APPROVED, AWSLC_APPROVED, AWSLC_APPROVED }, - - { NID_secp256k1, &EVP_sha1, AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED }, - { NID_secp256k1, &EVP_sha224, AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED }, - { NID_secp256k1, &EVP_sha256, AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED }, - { NID_secp256k1, &EVP_sha384, AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED }, - { NID_secp256k1, &EVP_sha512, AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED }, -}; - -class ECDSA_ServiceIndicatorTest : public awslc::TestWithNoErrors {}; -INSTANTIATE_TEST_SUITE_P(All, ECDSA_ServiceIndicatorTest, testing::ValuesIn(kECDSATestVectors)); - -TEST_P(ECDSA_ServiceIndicatorTest, ECDSAKeyCheck) { - const ECDSATestVector &ecdsaTestVector = GetParam(); +static const struct ECDSATestVector kECDSATestVectors[] = { + // Only the following NIDs for |EC_GROUP| are creatable with + // |EC_GROUP_new_by_curve_name|, and |NID_secp256k1| will only work if + // |kCurveSecp256k1Supported| is true. + {NID_secp224r1, &EVP_sha1, AWSLC_APPROVED, AWSLC_NOT_APPROVED, + AWSLC_APPROVED}, + {NID_secp224r1, &EVP_sha224, AWSLC_APPROVED, AWSLC_APPROVED, + AWSLC_APPROVED}, + {NID_secp224r1, &EVP_sha256, AWSLC_APPROVED, AWSLC_APPROVED, + AWSLC_APPROVED}, + {NID_secp224r1, &EVP_sha384, AWSLC_APPROVED, AWSLC_APPROVED, + AWSLC_APPROVED}, + {NID_secp224r1, &EVP_sha512, AWSLC_APPROVED, AWSLC_APPROVED, + AWSLC_APPROVED}, + + {NID_X9_62_prime256v1, &EVP_sha1, AWSLC_APPROVED, + AWSLC_NOT_APPROVED, AWSLC_APPROVED}, + {NID_X9_62_prime256v1, &EVP_sha224, AWSLC_APPROVED, + AWSLC_APPROVED, AWSLC_APPROVED}, + {NID_X9_62_prime256v1, &EVP_sha256, AWSLC_APPROVED, + AWSLC_APPROVED, AWSLC_APPROVED}, + {NID_X9_62_prime256v1, &EVP_sha384, AWSLC_APPROVED, + AWSLC_APPROVED, AWSLC_APPROVED}, + {NID_X9_62_prime256v1, &EVP_sha512, AWSLC_APPROVED, + AWSLC_APPROVED, AWSLC_APPROVED}, + + {NID_secp384r1, &EVP_sha1, AWSLC_APPROVED, AWSLC_NOT_APPROVED, + AWSLC_APPROVED}, + {NID_secp384r1, &EVP_sha224, AWSLC_APPROVED, AWSLC_APPROVED, + AWSLC_APPROVED}, + {NID_secp384r1, &EVP_sha256, AWSLC_APPROVED, AWSLC_APPROVED, + AWSLC_APPROVED}, + {NID_secp384r1, &EVP_sha384, AWSLC_APPROVED, AWSLC_APPROVED, + AWSLC_APPROVED}, + {NID_secp384r1, &EVP_sha512, AWSLC_APPROVED, AWSLC_APPROVED, + AWSLC_APPROVED}, + + {NID_secp521r1, &EVP_sha1, AWSLC_APPROVED, AWSLC_NOT_APPROVED, + AWSLC_APPROVED}, + {NID_secp521r1, &EVP_sha224, AWSLC_APPROVED, AWSLC_APPROVED, + AWSLC_APPROVED}, + {NID_secp521r1, &EVP_sha256, AWSLC_APPROVED, AWSLC_APPROVED, + AWSLC_APPROVED}, + {NID_secp521r1, &EVP_sha384, AWSLC_APPROVED, AWSLC_APPROVED, + AWSLC_APPROVED}, + {NID_secp521r1, &EVP_sha512, AWSLC_APPROVED, AWSLC_APPROVED, + AWSLC_APPROVED}, + + {NID_secp256k1, &EVP_sha1, AWSLC_NOT_APPROVED, + AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED}, + {NID_secp256k1, &EVP_sha224, AWSLC_NOT_APPROVED, + AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED}, + {NID_secp256k1, &EVP_sha256, AWSLC_NOT_APPROVED, + AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED}, + {NID_secp256k1, &EVP_sha384, AWSLC_NOT_APPROVED, + AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED}, + {NID_secp256k1, &EVP_sha512, AWSLC_NOT_APPROVED, + AWSLC_NOT_APPROVED, AWSLC_NOT_APPROVED}, +}; + +class ECDSAServiceIndicatorTest : public TestWithNoErrors {}; + +INSTANTIATE_TEST_SUITE_P(All, ECDSAServiceIndicatorTest, + testing::ValuesIn(kECDSATestVectors)); + +TEST_P(ECDSAServiceIndicatorTest, ECDSAKeyCheck) { + const ECDSATestVector &test = GetParam(); + if (test.nid == NID_secp256k1 && !kCurveSecp256k1Supported) { + GTEST_SKIP(); + } - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; // Test service indicator approval for |EC_KEY_generate_key_fips| and // |EC_KEY_check_fips|. - bssl::UniquePtr key(EC_KEY_new_by_curve_name(ecdsaTestVector.nid)); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EC_KEY_generate_key_fips(key.get()))); - ASSERT_EQ(approved, ecdsaTestVector.key_check_expect_approved); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EC_KEY_check_fips(key.get()))); - ASSERT_EQ(approved, ecdsaTestVector.key_check_expect_approved); - // Remove reference to private key in generated key and see if - // |EC_KEY_check_fips| still returns approval for keys with only public keys - // available. - bssl::UniquePtr key_only_public(EC_KEY_new_by_curve_name(ecdsaTestVector.nid)); - ASSERT_TRUE(EC_KEY_set_public_key(key_only_public.get(), EC_KEY_get0_public_key(key.get()))); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EC_KEY_check_fips(key_only_public.get()))); - ASSERT_EQ(approved, ecdsaTestVector.key_check_expect_approved); + bssl::UniquePtr key(EC_KEY_new_by_curve_name(test.nid)); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(EC_KEY_generate_key_fips(key.get()))); + EXPECT_EQ(approved, test.key_check_expect_approved); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(EC_KEY_check_fips(key.get()))); + EXPECT_EQ(approved, test.key_check_expect_approved); + + // See if |EC_KEY_check_fips| still returns approval with only the public + // component. + bssl::UniquePtr key_only_public(EC_KEY_new_by_curve_name(test.nid)); + ASSERT_TRUE(EC_KEY_set_public_key(key_only_public.get(), + EC_KEY_get0_public_key(key.get()))); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(EC_KEY_check_fips(key_only_public.get()))); + EXPECT_EQ(approved, test.key_check_expect_approved); + + if (kEVPKeyGenShouldCallFIPSFunctions) { + // Test running the EVP_PKEY_keygen interfaces one by one directly, and + // check |EVP_PKEY_keygen| for approval at the end. |EVP_PKEY_keygen_init| + // should not be approved because it does not indicate that an entire + // service has been completed. + bssl::UniquePtr ctx( + EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr)); + EVP_PKEY *raw = nullptr; + ASSERT_TRUE(ctx); + ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get())); + ASSERT_TRUE(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx.get(), test.nid)); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw))); + EXPECT_EQ(approved, test.key_check_expect_approved); - // Test running the EVP_PKEY_keygen interfaces one by one directly, and check - // |EVP_PKEY_keygen| for approval at the end. |EVP_PKEY_keygen_init| should - // not be approved because they do not indicate an entire service has been - // done. - bssl::UniquePtr ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr)); - EVP_PKEY *raw = nullptr; - ASSERT_TRUE(ctx); - ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get())); - ASSERT_TRUE(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx.get(), ecdsaTestVector.nid)); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw))); - // Prevent memory leakage. - bssl::UniquePtr pkey(raw); - raw = nullptr; - ASSERT_EQ(approved, ecdsaTestVector.key_check_expect_approved); + EVP_PKEY_free(raw); + } } -TEST_P(ECDSA_ServiceIndicatorTest, ECDSASigGen) { - const ECDSATestVector &ecdsaTestVector = GetParam(); +TEST_P(ECDSAServiceIndicatorTest, ECDSASigGen) { + const ECDSATestVector &test = GetParam(); + if (test.nid == NID_secp256k1 && !kCurveSecp256k1Supported) { + GTEST_SKIP(); + } - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; - bssl::UniquePtr group( - EC_GROUP_new_by_curve_name(ecdsaTestVector.nid)); + bssl::UniquePtr group(EC_GROUP_new_by_curve_name(test.nid)); bssl::UniquePtr eckey(EC_KEY_new()); bssl::UniquePtr pkey(EVP_PKEY_new()); bssl::ScopedEVP_MD_CTX md_ctx; ASSERT_TRUE(eckey); ASSERT_TRUE(EC_KEY_set_group(eckey.get(), group.get())); - // Generate a generic ec key. - EC_KEY_generate_key(eckey.get()); + // Generate a generic EC key. + ASSERT_TRUE(EC_KEY_generate_key(eckey.get())); ASSERT_TRUE(EVP_PKEY_set1_EC_KEY(pkey.get(), eckey.get())); // Test running the EVP_DigestSign interfaces one by one directly, and check // |EVP_DigestSignFinal| for approval at the end. |EVP_DigestSignInit|, // |EVP_DigestSignUpdate| should not be approved because they do not indicate // an entire service has been done. - std::vector final_output; - size_t sig_len; - CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, ecdsaTestVector.func(), nullptr, pkey.get()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, + test.func(), nullptr, + pkey.get()))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestSignUpdate(md_ctx.get(), kPlaintext, sizeof(kPlaintext)))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - // Determine the size of the signature. The first call of |EVP_DigestSignFinal| - // should not return an approval check because no crypto is being done when - // |nullptr| is inputted in the |*out_sig| field. + ASSERT_TRUE(EVP_DigestSignUpdate(md_ctx.get(), kPlaintext, + sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + // Determine the size of the signature. The first call of + // |EVP_DigestSignFinal| should not return an approval check because no crypto + // is being done when |nullptr| is given as the |out_sig| field. + size_t max_sig_len; CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), nullptr, &sig_len))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - final_output.resize(sig_len); + ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), nullptr, &max_sig_len))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + std::vector signature(max_sig_len); // The second call performs the actual operation. + size_t sig_len = max_sig_len; CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), final_output.data(), &sig_len))); - ASSERT_EQ(approved, ecdsaTestVector.sig_gen_expect_approved); - + ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), signature.data(), + &sig_len))); + ASSERT_LE(sig_len, signature.size()); + EXPECT_EQ(approved, test.sig_gen_expect_approved); // Test using the one-shot |EVP_DigestSign| function for approval. md_ctx.Reset(); - std::vector oneshot_output; CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, ecdsaTestVector.func(), nullptr, pkey.get()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), nullptr, &sig_len)); - oneshot_output.resize(sig_len); + ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, test.func(), + nullptr, pkey.get()))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + sig_len = max_sig_len; CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), oneshot_output.data(), &sig_len, - kPlaintext, sizeof(kPlaintext)))); - ASSERT_EQ(approved, ecdsaTestVector.sig_gen_expect_approved); + ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), signature.data(), &sig_len, + kPlaintext, sizeof(kPlaintext)))); + ASSERT_LE(sig_len, signature.size()); + EXPECT_EQ(approved, test.sig_gen_expect_approved); } -TEST_P(ECDSA_ServiceIndicatorTest, ECDSASigVer) { - const ECDSATestVector &ecdsaTestVector = GetParam(); +TEST_P(ECDSAServiceIndicatorTest, ECDSASigVer) { + const ECDSATestVector &test = GetParam(); + if (test.nid == NID_secp256k1 && !kCurveSecp256k1Supported) { + GTEST_SKIP(); + } - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; - bssl::UniquePtr group( - EC_GROUP_new_by_curve_name(ecdsaTestVector.nid)); + bssl::UniquePtr group(EC_GROUP_new_by_curve_name(test.nid)); bssl::UniquePtr eckey(EC_KEY_new()); bssl::UniquePtr pkey(EVP_PKEY_new()); bssl::ScopedEVP_MD_CTX md_ctx; @@ -1382,12 +1633,12 @@ TEST_P(ECDSA_ServiceIndicatorTest, ECDSASigVer) { ASSERT_TRUE(EC_KEY_set_group(eckey.get(), group.get())); // Generate ECDSA signatures for ECDSA verification. - EC_KEY_generate_key(eckey.get()); + ASSERT_TRUE(EC_KEY_generate_key(eckey.get())); ASSERT_TRUE(EVP_PKEY_set1_EC_KEY(pkey.get(), eckey.get())); std::vector signature; size_t sig_len = 0; - ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, ecdsaTestVector.func(), - nullptr, pkey.get())); + ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, test.func(), nullptr, + pkey.get())); ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), nullptr, &sig_len)); signature.resize(sig_len); ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), signature.data(), &sig_len, @@ -1398,44 +1649,47 @@ TEST_P(ECDSA_ServiceIndicatorTest, ECDSASigVer) { // Test running the EVP_DigestVerify interfaces one by one directly, and check // |EVP_DigestVerifyFinal| for approval at the end. |EVP_DigestVerifyInit|, - // |EVP_DigestVerifyUpdate| should not be approved because they do not indicate - // an entire service has been done. + // |EVP_DigestVerifyUpdate| should not be approved because they do not + // indicate an entire service has been done. md_ctx.Reset(); CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx.get(), nullptr, ecdsaTestVector.func(), nullptr, pkey.get()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx.get(), nullptr, test.func(), + nullptr, pkey.get()))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestVerifyUpdate(md_ctx.get(), kPlaintext, sizeof(kPlaintext)))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + ASSERT_TRUE(EVP_DigestVerifyUpdate(md_ctx.get(), kPlaintext, + sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestVerifyFinal(md_ctx.get(), signature.data(), signature.size()))); - ASSERT_EQ(approved, ecdsaTestVector.sig_ver_expect_approved); + ASSERT_TRUE(EVP_DigestVerifyFinal(md_ctx.get(), signature.data(), + signature.size()))); + EXPECT_EQ(approved, test.sig_ver_expect_approved); // Test using the one-shot |EVP_DigestVerify| function for approval. md_ctx.Reset(); CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx.get(), nullptr, ecdsaTestVector.func(), nullptr, pkey.get()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED( - approved, ASSERT_TRUE(EVP_DigestVerify(md_ctx.get(), signature.data(), - signature.size(), kPlaintext, - sizeof(kPlaintext)))); - ASSERT_EQ(approved, ecdsaTestVector.sig_ver_expect_approved); + ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx.get(), nullptr, test.func(), + nullptr, pkey.get()))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(EVP_DigestVerify(md_ctx.get(), signature.data(), + signature.size(), kPlaintext, + sizeof(kPlaintext)))); + EXPECT_EQ(approved, test.sig_ver_expect_approved); } // Test that |EVP_DigestSignFinal| and |EVP_DigestSignVerify| are approved with // manually constructing using the context setting functions. -TEST_P(ECDSA_ServiceIndicatorTest, ManualECDSASignVerify) { - const ECDSATestVector &ecdsaTestVector = GetParam(); +TEST_P(ECDSAServiceIndicatorTest, ManualECDSASignVerify) { + const ECDSATestVector &test = GetParam(); - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; bssl::ScopedEVP_MD_CTX ctx; - ASSERT_TRUE(EVP_DigestInit(ctx.get(), ecdsaTestVector.func())); + ASSERT_TRUE(EVP_DigestInit(ctx.get(), test.func())); ASSERT_TRUE(EVP_DigestUpdate(ctx.get(), kPlaintext, sizeof(kPlaintext))); - bssl::UniquePtr group( - EC_GROUP_new_by_curve_name(ecdsaTestVector.nid)); + bssl::UniquePtr group(EC_GROUP_new_by_curve_name(test.nid)); bssl::UniquePtr eckey(EC_KEY_new()); bssl::UniquePtr pkey(EVP_PKEY_new()); bssl::ScopedEVP_MD_CTX md_ctx; @@ -1449,29 +1703,29 @@ TEST_P(ECDSA_ServiceIndicatorTest, ManualECDSASignVerify) { // Manual construction for signing. bssl::UniquePtr pctx(EVP_PKEY_CTX_new(pkey.get(), nullptr)); ASSERT_TRUE(EVP_PKEY_sign_init(pctx.get())); - ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(pctx.get(), ecdsaTestVector.func())); + ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(pctx.get(), test.func())); EVP_MD_CTX_set_pkey_ctx(ctx.get(), pctx.get()); // Determine the size of the signature. size_t sig_len = 0; CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestSignFinal(ctx.get(), nullptr, &sig_len))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + ASSERT_TRUE(EVP_DigestSignFinal(ctx.get(), nullptr, &sig_len))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); std::vector sig; sig.resize(sig_len); CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestSignFinal(ctx.get(), sig.data(), &sig_len))); - ASSERT_EQ(approved, ecdsaTestVector.sig_gen_expect_approved); + ASSERT_TRUE(EVP_DigestSignFinal(ctx.get(), sig.data(), &sig_len))); + EXPECT_EQ(approved, test.sig_gen_expect_approved); sig.resize(sig_len); // Manual construction for verification. ASSERT_TRUE(EVP_PKEY_verify_init(pctx.get())); - ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(pctx.get(), ecdsaTestVector.func())); + ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(pctx.get(), test.func())); EVP_MD_CTX_set_pkey_ctx(ctx.get(), pctx.get()); CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_TRUE(EVP_DigestVerifyFinal(ctx.get(), sig.data(), sig_len))); - ASSERT_EQ(approved, ecdsaTestVector.sig_ver_expect_approved); + ASSERT_TRUE(EVP_DigestVerifyFinal(ctx.get(), sig.data(), sig_len))); + EXPECT_EQ(approved, test.sig_ver_expect_approved); } struct ECDHTestVector { @@ -1480,9 +1734,9 @@ struct ECDHTestVector { // md_func is the digest to test. const int digest_length; // expected to be approved or not. - const int expect_approved; + const FIPSStatus expect_approved; }; -struct ECDHTestVector kECDHTestVectors[] = { +static const struct ECDHTestVector kECDHTestVectors[] = { // Only the following NIDs for |EC_GROUP| are creatable with // |EC_GROUP_new_by_curve_name|. // |ECDH_compute_key_fips| fails directly when an invalid hash length is @@ -1513,16 +1767,20 @@ struct ECDHTestVector kECDHTestVectors[] = { { NID_secp256k1, SHA512_DIGEST_LENGTH, AWSLC_NOT_APPROVED }, }; -class ECDH_ServiceIndicatorTest : public awslc::TestWithNoErrors {}; +class ECDH_ServiceIndicatorTest : public TestWithNoErrors {}; -INSTANTIATE_TEST_SUITE_P(All, ECDH_ServiceIndicatorTest, testing::ValuesIn(kECDHTestVectors)); +INSTANTIATE_TEST_SUITE_P(All, ECDH_ServiceIndicatorTest, + testing::ValuesIn(kECDHTestVectors)); TEST_P(ECDH_ServiceIndicatorTest, ECDH) { - const ECDHTestVector &ecdhTestVector = GetParam(); + const ECDHTestVector &test = GetParam(); + if (test.nid == NID_secp256k1 && !kCurveSecp256k1Supported) { + GTEST_SKIP(); + } - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; - bssl::UniquePtr group(EC_GROUP_new_by_curve_name(ecdhTestVector.nid)); + bssl::UniquePtr group(EC_GROUP_new_by_curve_name(test.nid)); bssl::UniquePtr our_key(EC_KEY_new()); bssl::UniquePtr peer_key(EC_KEY_new()); bssl::ScopedEVP_MD_CTX md_ctx; @@ -1540,79 +1798,85 @@ TEST_P(ECDH_ServiceIndicatorTest, ECDH) { // Test that |ECDH_compute_key_fips| has service indicator approval as // expected. - std::vector digest(ecdhTestVector.digest_length); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(ECDH_compute_key_fips(digest.data(), - digest.size(), EC_KEY_get0_public_key(peer_key.get()), our_key.get()))); - ASSERT_EQ(approved, ecdhTestVector.expect_approved); + std::vector digest(test.digest_length); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(ECDH_compute_key_fips(digest.data(), digest.size(), + EC_KEY_get0_public_key(peer_key.get()), + our_key.get()))); + EXPECT_EQ(approved, test.expect_approved); // Test running the EVP_PKEY_derive interfaces one by one directly, and check - // |EVP_PKEY_derive| for approval at the end. |EVP_PKEY_derive_init|, - // |EVP_PKEY_derive_set_peer| should not be approved because they do not indicate - // an entire service has been done. - std::vector derive_output; - size_t out_len = 0; + // |EVP_PKEY_derive| for approval at the end. |EVP_PKEY_derive_init| and + // |EVP_PKEY_derive_set_peer| should not be approved because they do not + // indicate an entire service has been done. bssl::UniquePtr our_pkey(EVP_PKEY_new()); ASSERT_TRUE(EVP_PKEY_set1_EC_KEY(our_pkey.get(), our_key.get())); - bssl::UniquePtr our_ctx(EVP_PKEY_CTX_new(our_pkey.get(), nullptr)); + bssl::UniquePtr our_ctx( + EVP_PKEY_CTX_new(our_pkey.get(), nullptr)); bssl::UniquePtr peer_pkey(EVP_PKEY_new()); ASSERT_TRUE(EVP_PKEY_set1_EC_KEY(peer_pkey.get(), peer_key.get())); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EVP_PKEY_derive_init(our_ctx.get()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EVP_PKEY_derive_set_peer(our_ctx.get(), peer_pkey.get()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(EVP_PKEY_derive_init(our_ctx.get()))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(EVP_PKEY_derive_set_peer(our_ctx.get(), peer_pkey.get()))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); // Determine the size of the output key. The first call of |EVP_PKEY_derive| // should not return an approval check because no crypto is being done when // |nullptr| is inputted in the |*key| field - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EVP_PKEY_derive(our_ctx.get(), nullptr, &out_len))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - derive_output.resize(out_len); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(EVP_PKEY_derive(our_ctx.get(), derive_output.data(), &out_len))); - derive_output.resize(out_len); - ASSERT_EQ(approved, ecdhTestVector.expect_approved); + size_t out_len = 0; + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(EVP_PKEY_derive(our_ctx.get(), nullptr, &out_len))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + std::vector derive_output(out_len); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(EVP_PKEY_derive(our_ctx.get(), derive_output.data(), + &out_len))); + EXPECT_EQ(approved, kEVPDeriveSetsServiceIndicator + ? test.expect_approved + : AWSLC_NOT_APPROVED); } -struct KDFTestVector { +static const struct KDFTestVector { // func is the hash function for KDF to test. const EVP_MD *(*func)(); const uint8_t *expected_output; - const int expect_approved; + const FIPSStatus expect_approved; } kKDFTestVectors[] = { - { EVP_md5, kTLSOutput_md, AWSLC_APPROVED }, - { EVP_sha1, kTLSOutput_sha1, AWSLC_APPROVED }, - { EVP_md5_sha1, kTLSOutput_mdsha1, AWSLC_APPROVED }, - { EVP_sha224, kTLSOutput_sha224, AWSLC_NOT_APPROVED }, - { EVP_sha256, kTLSOutput_sha256, AWSLC_APPROVED }, - { EVP_sha384, kTLSOutput_sha384, AWSLC_APPROVED }, - { EVP_sha512, kTLSOutput_sha512, AWSLC_APPROVED }, + {EVP_md5, kTLSOutput_md, AWSLC_APPROVED}, + {EVP_sha1, kTLSOutput_sha1, AWSLC_APPROVED}, + {EVP_md5_sha1, kTLSOutput_mdsha1, AWSLC_APPROVED}, + {EVP_sha224, kTLSOutput_sha224, AWSLC_NOT_APPROVED}, + {EVP_sha256, kTLSOutput_sha256, AWSLC_APPROVED}, + {EVP_sha384, kTLSOutput_sha384, AWSLC_APPROVED}, + {EVP_sha512, kTLSOutput_sha512, AWSLC_APPROVED}, }; -class KDF_ServiceIndicatorTest : public awslc::TestWithNoErrors {}; +class KDF_ServiceIndicatorTest : public TestWithNoErrors {}; -INSTANTIATE_TEST_SUITE_P(All, KDF_ServiceIndicatorTest, testing::ValuesIn(kKDFTestVectors)); +INSTANTIATE_TEST_SUITE_P(All, KDF_ServiceIndicatorTest, + testing::ValuesIn(kKDFTestVectors)); -TEST_P(KDF_ServiceIndicatorTest, KDF) { - const KDFTestVector &kdfTestVector = GetParam(); +TEST_P(KDF_ServiceIndicatorTest, TLSKDF) { + const KDFTestVector &test = GetParam(); - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; - std::vector tls_output(32); + uint8_t output[32]; CALL_SERVICE_AND_CHECK_APPROVED( - approved, ASSERT_TRUE(CRYPTO_tls1_prf(kdfTestVector.func(), - tls_output.data(), tls_output.size(), + approved, ASSERT_TRUE(CRYPTO_tls1_prf(test.func(), output, sizeof(output), kTLSSecret, sizeof(kTLSSecret), kTLSLabel, sizeof(kTLSLabel), kTLSSeed1, sizeof(kTLSSeed1), kTLSSeed2, sizeof(kTLSSeed2)))); - ASSERT_TRUE(check_test(kdfTestVector.expected_output, tls_output.data(), - tls_output.size(), "TLS KDF KAT")); - ASSERT_EQ(approved, kdfTestVector.expect_approved); + EXPECT_EQ(Bytes(test.expected_output, sizeof(output)), + Bytes(output, sizeof(output))); + EXPECT_EQ(approved, test.expect_approved); } TEST(ServiceIndicatorTest, CMAC) { - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; - std::vector mac(16); - size_t out_len; bssl::UniquePtr ctx(CMAC_CTX_new()); ASSERT_TRUE(ctx); @@ -1620,61 +1884,78 @@ TEST(ServiceIndicatorTest, CMAC) { // |CMAC_Final| for approval at the end. |CMAC_Init| and |CMAC_Update| // should not be approved, because the functions do not indicate that a // service has been fully completed yet. - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(CMAC_Init(ctx.get(), kAESKey, sizeof(kAESKey), EVP_aes_128_cbc(), nullptr))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(CMAC_Update(ctx.get(), kPlaintext, sizeof(kPlaintext)))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(CMAC_Final(ctx.get(), mac.data(), &out_len))); - ASSERT_EQ(approved, AWSLC_APPROVED); - ASSERT_TRUE(check_test(kAESCMACOutput, mac.data(), sizeof(kAESCMACOutput), "AES-CMAC KAT")); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(CMAC_Init(ctx.get(), kAESKey, sizeof(kAESKey), + EVP_aes_128_cbc(), nullptr))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(CMAC_Update(ctx.get(), kPlaintext, sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + + uint8_t mac[16]; + size_t out_len; + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(CMAC_Final(ctx.get(), mac, &out_len))); + EXPECT_EQ(approved, AWSLC_APPROVED); + EXPECT_EQ(Bytes(kAESCMACOutput), Bytes(mac)); // Test using the one-shot API for approval. - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(AES_CMAC(mac.data(), kAESKey, sizeof(kAESKey), - kPlaintext, sizeof(kPlaintext)))); - ASSERT_TRUE(check_test(kAESCMACOutput, mac.data(), sizeof(kAESCMACOutput), "AES-CMAC KAT")); - ASSERT_EQ(approved, AWSLC_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(AES_CMAC(mac, kAESKey, sizeof(kAESKey), kPlaintext, + sizeof(kPlaintext)))); + EXPECT_EQ(Bytes(kAESCMACOutput), Bytes(mac)); + EXPECT_EQ(approved, AWSLC_APPROVED); } TEST(ServiceIndicatorTest, BasicTest) { - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; bssl::ScopedEVP_AEAD_CTX aead_ctx; AES_KEY aes_key; uint8_t aes_iv[sizeof(kAESIV)]; uint8_t output[256]; + uint8_t ofb_output[sizeof(kPlaintext)]; size_t out_len; int num = 0; - int counter_before, counter_after; + uint64_t counter_before, counter_after; ASSERT_TRUE(EVP_AEAD_CTX_init(aead_ctx.get(), EVP_aead_aes_128_gcm_randnonce(), kAESKey, sizeof(kAESKey), 0, nullptr)); - // Because the service indicator gets initialised in |FIPS_service_indicator_update_state|, which - // is called by all approved services, the self_test run at the beginning would have updated it - // more than once. The following test ensures that it's not zero and that it gets updated by calling - // an approved service without calling |FIPS_service_indicator_before_call| first, which can init the counter, - // but instead calling |FIPS_service_indicator_after_call| - // This test also ensures that the counter gets incremented once, i.e. it was locked through the internal calls. + // Because the service indicator gets initialised in + // |FIPS_service_indicator_update_state|, which is called by all approved + // services, the self_test run at the beginning would have updated it more + // than once. The following test ensures that it's not zero and that it gets + // updated by calling an approved service without calling + // |FIPS_service_indicator_before_call| first, which can init the counter, but + // instead calling |FIPS_service_indicator_after_call| + // This test also ensures that the counter gets incremented once, i.e. it was + // locked through the internal calls. counter_before = FIPS_service_indicator_after_call(); - ASSERT_NE(counter_before, 0); - EVP_AEAD_CTX_seal(aead_ctx.get(), - output, &out_len, sizeof(output), nullptr, 0, kPlaintext, sizeof(kPlaintext), nullptr, 0); + ASSERT_NE(counter_before, (uint64_t)0); + EVP_AEAD_CTX_seal(aead_ctx.get(), output, &out_len, sizeof(output), nullptr, + 0, kPlaintext, sizeof(kPlaintext), nullptr, 0); counter_after = FIPS_service_indicator_after_call(); ASSERT_EQ(counter_after, counter_before+1); // Call an approved service. - CALL_SERVICE_AND_CHECK_APPROVED(approved, EVP_AEAD_CTX_seal(aead_ctx.get(), - output, &out_len, sizeof(output), nullptr, 0, kPlaintext, sizeof(kPlaintext), nullptr, 0)); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + EVP_AEAD_CTX_seal(aead_ctx.get(), output, &out_len, sizeof(output), + nullptr, 0, kPlaintext, sizeof(kPlaintext), nullptr, 0)); ASSERT_EQ(approved, AWSLC_APPROVED); // Call an approved service in a macro. - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_EQ(EVP_AEAD_CTX_seal(aead_ctx.get(), - output, &out_len, sizeof(output), nullptr, 0, kPlaintext, sizeof(kPlaintext), nullptr, 0), 1)); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_EQ(EVP_AEAD_CTX_seal(aead_ctx.get(), output, &out_len, + sizeof(output), nullptr, 0, kPlaintext, + sizeof(kPlaintext), nullptr, 0), 1)); ASSERT_EQ(approved, AWSLC_APPROVED); // Call an approved service and compare expected return value. int return_val = 0; - CALL_SERVICE_AND_CHECK_APPROVED(approved, return_val = EVP_AEAD_CTX_seal(aead_ctx.get(), - output, &out_len, sizeof(output), nullptr, 0, kPlaintext, sizeof(kPlaintext), nullptr, 0)); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + return_val = EVP_AEAD_CTX_seal(aead_ctx.get(), output, &out_len, + sizeof(output), nullptr, 0, kPlaintext, + sizeof(kPlaintext), nullptr, 0)); ASSERT_EQ(return_val, 1); ASSERT_EQ(approved, AWSLC_APPROVED); @@ -1692,8 +1973,10 @@ TEST(ServiceIndicatorTest, BasicTest) { // Fail an approved service on purpose. return_val = 0; - CALL_SERVICE_AND_CHECK_APPROVED(approved, return_val = EVP_AEAD_CTX_seal(aead_ctx.get(), - output, &out_len, 0, nullptr, 0, kPlaintext, sizeof(kPlaintext), nullptr, 0)); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + return_val = EVP_AEAD_CTX_seal(aead_ctx.get(), output, &out_len, 0, + nullptr, 0, kPlaintext, sizeof(kPlaintext), + nullptr, 0)); ASSERT_EQ(return_val, 0); ASSERT_EQ(approved, AWSLC_NOT_APPROVED); @@ -1712,448 +1995,490 @@ TEST(ServiceIndicatorTest, BasicTest) { // Call a non-approved service. memcpy(aes_iv, kAESIV, sizeof(kAESIV)); ASSERT_TRUE(AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_ofb128_encrypt(kPlaintext, output, - sizeof(kPlaintext), &aes_key, aes_iv, &num)); - ASSERT_TRUE(check_test(kAESOFBCiphertext, output, sizeof(kAESOFBCiphertext), - "AES-OFB Encryption KAT")); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + AES_ofb128_encrypt(kPlaintext, ofb_output, sizeof(kPlaintext), &aes_key, + aes_iv, &num)); + EXPECT_EQ(Bytes(kAESOFBCiphertext), Bytes(ofb_output)); ASSERT_EQ(approved, AWSLC_NOT_APPROVED); } // Test the SHA interfaces one by one and check that only |*_Final| does the // approval at the end. TEST(ServiceIndicatorTest, SHA) { - int approved = AWSLC_NOT_APPROVED; - - std::vector plaintext(kPlaintext, kPlaintext + sizeof(kPlaintext)); + FIPSStatus approved = AWSLC_NOT_APPROVED; std::vector digest; digest.resize(MD4_DIGEST_LENGTH); MD4_CTX md4_ctx; CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(MD4_Init(&md4_ctx))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(MD4_Update(&md4_ctx, plaintext.data(), plaintext.size()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(MD4_Final(digest.data(), &md4_ctx))); - ASSERT_TRUE(check_test(kOutput_md4, digest.data(), sizeof(kOutput_md4), "MD4 Hash KAT")); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(MD4_Update(&md4_ctx, kPlaintext, sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(MD4_Final(digest.data(), &md4_ctx))); + EXPECT_EQ(Bytes(kOutput_md4), Bytes(digest)); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); digest.resize(MD5_DIGEST_LENGTH); MD5_CTX md5_ctx; CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(MD5_Init(&md5_ctx))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(MD5_Update(&md5_ctx, plaintext.data(), plaintext.size()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(MD5_Final(digest.data(), &md5_ctx))); - ASSERT_TRUE(check_test(kOutput_md5, digest.data(), sizeof(kOutput_md5), "MD5 Hash KAT")); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(MD5_Update(&md5_ctx, kPlaintext, sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(MD5_Final(digest.data(), &md5_ctx))); + EXPECT_EQ(Bytes(kOutput_md5), Bytes(digest)); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); - digest.clear(); digest.resize(SHA_DIGEST_LENGTH); SHA_CTX sha_ctx; CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA1_Init(&sha_ctx))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA1_Update(&sha_ctx, plaintext.data(), plaintext.size()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA1_Final(digest.data(), &sha_ctx))); - ASSERT_TRUE(check_test(kOutput_sha1, digest.data(), sizeof(kOutput_sha1), "SHA1 Hash KAT")); - ASSERT_EQ(approved, AWSLC_APPROVED); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA1_Update(&sha_ctx, kPlaintext, sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA1_Final(digest.data(), &sha_ctx))); + EXPECT_EQ(Bytes(kOutput_sha1), Bytes(digest)); + EXPECT_EQ(approved, AWSLC_APPROVED); - digest.clear(); digest.resize(SHA224_DIGEST_LENGTH); SHA256_CTX sha224_ctx; - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA224_Init(&sha224_ctx))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA224_Update(&sha224_ctx, plaintext.data(), plaintext.size()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA224_Final(digest.data(), &sha224_ctx))); - ASSERT_TRUE(check_test(kOutput_sha224, digest.data(), sizeof(kOutput_sha224), "SHA224 Hash KAT")); - ASSERT_EQ(approved, AWSLC_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA224_Init(&sha224_ctx))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA224_Update(&sha224_ctx, kPlaintext, sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA224_Final(digest.data(), &sha224_ctx))); + EXPECT_EQ(Bytes(kOutput_sha224), Bytes(digest)); + EXPECT_EQ(approved, AWSLC_APPROVED); - digest.clear(); digest.resize(SHA256_DIGEST_LENGTH); SHA256_CTX sha256_ctx; - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA256_Init(&sha256_ctx))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA256_Update(&sha256_ctx, plaintext.data(), plaintext.size()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA256_Final(digest.data(), &sha256_ctx))); - ASSERT_TRUE(check_test(kOutput_sha256, digest.data(), sizeof(kOutput_sha256), "SHA256 Hash KAT")); - ASSERT_EQ(approved, AWSLC_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA256_Init(&sha256_ctx))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA256_Update(&sha256_ctx, kPlaintext, sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA256_Final(digest.data(), &sha256_ctx))); + EXPECT_EQ(Bytes(kOutput_sha256), Bytes(digest)); + EXPECT_EQ(approved, AWSLC_APPROVED); - digest.clear(); digest.resize(SHA384_DIGEST_LENGTH); SHA512_CTX sha384_ctx; - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA384_Init(&sha384_ctx))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA384_Update(&sha384_ctx, plaintext.data(), plaintext.size()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA384_Final(digest.data(), &sha384_ctx))); - ASSERT_TRUE(check_test(kOutput_sha384, digest.data(), sizeof(kOutput_sha384), "SHA384 Hash KAT")); - ASSERT_EQ(approved, AWSLC_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA384_Init(&sha384_ctx))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA384_Update(&sha384_ctx, kPlaintext, sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA384_Final(digest.data(), &sha384_ctx))); + EXPECT_EQ(Bytes(kOutput_sha384), Bytes(digest)); + EXPECT_EQ(approved, AWSLC_APPROVED); - digest.clear(); digest.resize(SHA512_DIGEST_LENGTH); SHA512_CTX sha512_ctx; - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA512_Init(&sha512_ctx))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA512_Update(&sha512_ctx, plaintext.data(), plaintext.size()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA512_Final(digest.data(), &sha512_ctx))); - ASSERT_TRUE(check_test(kOutput_sha512, digest.data(), sizeof(kOutput_sha512), "SHA512 Hash KAT")); - ASSERT_EQ(approved, AWSLC_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA512_Init(&sha512_ctx))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA512_Update(&sha512_ctx, kPlaintext, sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA512_Final(digest.data(), &sha512_ctx))); + EXPECT_EQ(Bytes(kOutput_sha512), Bytes(digest)); + EXPECT_EQ(approved, AWSLC_APPROVED); - digest.clear(); digest.resize(SHA512_256_DIGEST_LENGTH); SHA512_CTX sha512_256_ctx; - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA512_256_Init(&sha512_256_ctx))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA512_256_Update(&sha512_256_ctx, plaintext.data(), plaintext.size()))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(SHA512_256_Final(digest.data(), &sha512_256_ctx))); - ASSERT_TRUE(check_test(kOutput_sha512_256, digest.data(), sizeof(kOutput_sha512_256), "SHA512-256 Hash KAT")); - ASSERT_EQ(approved, AWSLC_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA512_256_Init(&sha512_256_ctx))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA512_256_Update(&sha512_256_ctx, kPlaintext, + sizeof(kPlaintext)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(SHA512_256_Final(digest.data(), &sha512_256_ctx))); + EXPECT_EQ(Bytes(kOutput_sha512_256), Bytes(digest)); + EXPECT_EQ(approved, AWSLC_APPROVED); } TEST(ServiceIndicatorTest, AESECB) { - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; AES_KEY aes_key; uint8_t output[256]; // AES-ECB Encryption KAT for 128 bit key. ASSERT_TRUE(AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) == 0); - // AES_ecb_encrypt encrypts (or decrypts) a single, 16 byte block from in to out. - for (size_t j = 0; j < sizeof(kPlaintext) / AES_BLOCK_SIZE; j++) { - CALL_SERVICE_AND_CHECK_APPROVED(approved, - AES_ecb_encrypt(&kPlaintext[j * AES_BLOCK_SIZE], &output[j * AES_BLOCK_SIZE], &aes_key, AES_ENCRYPT)); - ASSERT_EQ(approved, AWSLC_APPROVED); + // AES_ecb_encrypt encrypts (or decrypts) a single, 16 byte block from in to + // out. + for (size_t i = 0; i < sizeof(kPlaintext) / AES_BLOCK_SIZE; i++) { + CALL_SERVICE_AND_CHECK_APPROVED( + approved, + AES_ecb_encrypt(&kPlaintext[i * AES_BLOCK_SIZE], + &output[i * AES_BLOCK_SIZE], &aes_key, AES_ENCRYPT)); + EXPECT_EQ(approved, AWSLC_APPROVED); } - ASSERT_TRUE(check_test(kAESECBCiphertext, output, sizeof(kAESECBCiphertext), - "AES-ECB Encryption KAT for 128 bit key")); + EXPECT_EQ(Bytes(kAESECBCiphertext), Bytes(output, sizeof(kAESECBCiphertext))); // AES-ECB Decryption KAT for 128 bit key. ASSERT_TRUE(AES_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) == 0); - for (size_t j = 0; j < sizeof(kPlaintext) / AES_BLOCK_SIZE; j++) { - CALL_SERVICE_AND_CHECK_APPROVED(approved, - AES_ecb_encrypt(&kAESECBCiphertext[j * AES_BLOCK_SIZE], &output[j * AES_BLOCK_SIZE], &aes_key, AES_DECRYPT)); - ASSERT_EQ(approved, AWSLC_APPROVED); + for (size_t i = 0; i < sizeof(kPlaintext) / AES_BLOCK_SIZE; i++) { + CALL_SERVICE_AND_CHECK_APPROVED( + approved, + AES_ecb_encrypt(&kAESECBCiphertext[i * AES_BLOCK_SIZE], + &output[i * AES_BLOCK_SIZE], &aes_key, AES_DECRYPT)); + EXPECT_EQ(approved, AWSLC_APPROVED); } - ASSERT_TRUE(check_test(kPlaintext, output, sizeof(kPlaintext), - "AES-ECB Decryption KAT for 128 bit key")); + EXPECT_EQ(Bytes(kPlaintext), Bytes(output, sizeof(kPlaintext))); // AES-ECB Encryption KAT for 192 bit key. - ASSERT_TRUE(AES_set_encrypt_key(kAESKey_192, 8 * sizeof(kAESKey_192), &aes_key) == 0); - for (size_t j = 0; j < sizeof(kPlaintext) / AES_BLOCK_SIZE; j++) { - CALL_SERVICE_AND_CHECK_APPROVED(approved, - AES_ecb_encrypt(&kPlaintext[j * AES_BLOCK_SIZE], &output[j * AES_BLOCK_SIZE], &aes_key, AES_ENCRYPT)); - ASSERT_EQ(approved, AWSLC_APPROVED); + ASSERT_TRUE( + AES_set_encrypt_key(kAESKey_192, 8 * sizeof(kAESKey_192), &aes_key) == 0); + for (size_t i = 0; i < sizeof(kPlaintext) / AES_BLOCK_SIZE; i++) { + CALL_SERVICE_AND_CHECK_APPROVED( + approved, + AES_ecb_encrypt(&kPlaintext[i * AES_BLOCK_SIZE], + &output[i * AES_BLOCK_SIZE], &aes_key, AES_ENCRYPT)); + EXPECT_EQ(approved, AWSLC_APPROVED); } - ASSERT_TRUE(check_test(kAESECBCiphertext_192, output, sizeof(kAESECBCiphertext_192), - "AES-ECB Encryption KAT for 192 bit key")); + EXPECT_EQ(Bytes(kAESECBCiphertext_192), + Bytes(output, sizeof(kAESECBCiphertext_192))); // AES-ECB Decryption KAT for 192 bit key. - ASSERT_TRUE(AES_set_decrypt_key(kAESKey_192, 8 * sizeof(kAESKey_192), &aes_key) == 0); - for (size_t j = 0; j < sizeof(kPlaintext) / AES_BLOCK_SIZE; j++) { - CALL_SERVICE_AND_CHECK_APPROVED(approved, - AES_ecb_encrypt(&kAESECBCiphertext_192[j * AES_BLOCK_SIZE], &output[j * AES_BLOCK_SIZE], &aes_key, AES_DECRYPT)); - ASSERT_EQ(approved, AWSLC_APPROVED); + ASSERT_TRUE( + AES_set_decrypt_key(kAESKey_192, 8 * sizeof(kAESKey_192), &aes_key) == 0); + for (size_t i = 0; i < sizeof(kPlaintext) / AES_BLOCK_SIZE; i++) { + CALL_SERVICE_AND_CHECK_APPROVED( + approved, + AES_ecb_encrypt(&kAESECBCiphertext_192[i * AES_BLOCK_SIZE], + &output[i * AES_BLOCK_SIZE], &aes_key, AES_DECRYPT)); + EXPECT_EQ(approved, AWSLC_APPROVED); } - ASSERT_TRUE(check_test(kPlaintext, output, sizeof(kPlaintext), - "AES-ECB Decryption KAT for 192 bit key")); + EXPECT_EQ(Bytes(kPlaintext), Bytes(output, sizeof(kPlaintext))); // AES-ECB Encryption KAT for 256 bit key. - ASSERT_TRUE(AES_set_encrypt_key(kAESKey_256, 8 * sizeof(kAESKey_256), &aes_key) == 0); - for (size_t j = 0; j < sizeof(kPlaintext) / AES_BLOCK_SIZE; j++) { - CALL_SERVICE_AND_CHECK_APPROVED(approved, - AES_ecb_encrypt(&kPlaintext[j * AES_BLOCK_SIZE], &output[j * AES_BLOCK_SIZE], &aes_key, AES_ENCRYPT)); - ASSERT_EQ(approved, AWSLC_APPROVED); + ASSERT_TRUE( + AES_set_encrypt_key(kAESKey_256, 8 * sizeof(kAESKey_256), &aes_key) == 0); + for (size_t i = 0; i < sizeof(kPlaintext) / AES_BLOCK_SIZE; i++) { + CALL_SERVICE_AND_CHECK_APPROVED( + approved, + AES_ecb_encrypt(&kPlaintext[i * AES_BLOCK_SIZE], + &output[i * AES_BLOCK_SIZE], &aes_key, AES_ENCRYPT)); + EXPECT_EQ(approved, AWSLC_APPROVED); } - ASSERT_TRUE(check_test(kAESECBCiphertext_256, output, sizeof(kAESECBCiphertext_256), - "AES-ECB Encryption KAT for 256 bit key")); + EXPECT_EQ(Bytes(kAESECBCiphertext_256), + Bytes(output, sizeof(kAESECBCiphertext_256))); // AES-ECB Decryption KAT for 256 bit key. - ASSERT_TRUE(AES_set_decrypt_key(kAESKey_256, 8 * sizeof(kAESKey_256), &aes_key) == 0); - for (size_t j = 0; j < sizeof(kPlaintext) / AES_BLOCK_SIZE; j++) { - CALL_SERVICE_AND_CHECK_APPROVED(approved, - AES_ecb_encrypt(&kAESECBCiphertext_256[j * AES_BLOCK_SIZE], &output[j * AES_BLOCK_SIZE], &aes_key, AES_DECRYPT)); - ASSERT_EQ(approved, AWSLC_APPROVED); + ASSERT_TRUE( + AES_set_decrypt_key(kAESKey_256, 8 * sizeof(kAESKey_256), &aes_key) == 0); + for (size_t i = 0; i < sizeof(kPlaintext) / AES_BLOCK_SIZE; i++) { + CALL_SERVICE_AND_CHECK_APPROVED( + approved, + AES_ecb_encrypt(&kAESECBCiphertext_256[i * AES_BLOCK_SIZE], + &output[i * AES_BLOCK_SIZE], &aes_key, AES_DECRYPT)); + EXPECT_EQ(approved, AWSLC_APPROVED); } - ASSERT_TRUE(check_test(kPlaintext, output, sizeof(kPlaintext), - "AES-ECB Decryption KAT for 256 bit key")); + EXPECT_EQ(Bytes(kPlaintext), Bytes(output, sizeof(kPlaintext))); } TEST(ServiceIndicatorTest, AESCBC) { - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; + AES_KEY aes_key; - uint8_t aes_iv[16]; - uint8_t output[256]; + uint8_t aes_iv[sizeof(kAESIV)]; + uint8_t output[sizeof(kPlaintext)]; + // AES-CBC Encryption KAT for 128 bit key. - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); ASSERT_TRUE(AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_cbc_encrypt(kPlaintext, output, - sizeof(kPlaintext), &aes_key, aes_iv, AES_ENCRYPT)); - ASSERT_TRUE(check_test(kAESCBCCiphertext, output, sizeof(kAESCBCCiphertext), - "AES-CBC Encryption KAT for 128 bit key")); - ASSERT_EQ(approved, AWSLC_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, AES_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), + &aes_key, aes_iv, AES_ENCRYPT)); + EXPECT_EQ(Bytes(kAESCBCCiphertext), Bytes(output)); + EXPECT_EQ(approved, AWSLC_APPROVED); // AES-CBC Decryption KAT for 128 bit key. - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); ASSERT_TRUE(AES_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_cbc_encrypt(kAESCBCCiphertext, output, - sizeof(kAESCBCCiphertext), &aes_key, aes_iv, AES_DECRYPT)); - ASSERT_TRUE(check_test(kPlaintext, output, sizeof(kPlaintext), - "AES-CBC Decryption KAT for 128 bit key")); - ASSERT_EQ(approved, AWSLC_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, + AES_cbc_encrypt(kAESCBCCiphertext, output, sizeof(kAESCBCCiphertext), + &aes_key, aes_iv, AES_DECRYPT)); + EXPECT_EQ(Bytes(kPlaintext), Bytes(output)); + EXPECT_EQ(approved, AWSLC_APPROVED); // AES-CBC Encryption KAT for 192 bit key. - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); - ASSERT_TRUE(AES_set_encrypt_key(kAESKey_192, 8 * sizeof(kAESKey_192), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_cbc_encrypt(kPlaintext, output, - sizeof(kPlaintext), &aes_key, aes_iv, AES_ENCRYPT)); - ASSERT_TRUE(check_test(kAESCBCCiphertext_192, output, sizeof(kAESCBCCiphertext_192), - "AES-CBC Encryption KAT for 192 bit key")); - ASSERT_EQ(approved, AWSLC_APPROVED); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); + ASSERT_TRUE( + AES_set_encrypt_key(kAESKey_192, 8 * sizeof(kAESKey_192), &aes_key) == 0); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, AES_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), + &aes_key, aes_iv, AES_ENCRYPT)); + EXPECT_EQ(Bytes(kAESCBCCiphertext_192), Bytes(output)); + EXPECT_EQ(approved, AWSLC_APPROVED); // AES-CBC Decryption KAT for 192 bit key. - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); - ASSERT_TRUE(AES_set_decrypt_key(kAESKey_192, 8 * sizeof(kAESKey_192), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_cbc_encrypt(kAESCBCCiphertext_192, output, - sizeof(kAESCBCCiphertext_192), &aes_key, aes_iv, AES_DECRYPT)); - ASSERT_TRUE(check_test(kPlaintext, output, sizeof(kPlaintext), - "AES-CBC Decryption KAT for 192 bit key")); - ASSERT_EQ(approved, AWSLC_APPROVED); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); + ASSERT_TRUE( + AES_set_decrypt_key(kAESKey_192, 8 * sizeof(kAESKey_192), &aes_key) == 0); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, AES_cbc_encrypt(kAESCBCCiphertext_192, output, + sizeof(kAESCBCCiphertext_192), &aes_key, aes_iv, + AES_DECRYPT)); + EXPECT_EQ(Bytes(kPlaintext), Bytes(output)); + EXPECT_EQ(approved, AWSLC_APPROVED); // AES-CBC Encryption KAT for 256 bit key. - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); - ASSERT_TRUE(AES_set_encrypt_key(kAESKey_256, 8 * sizeof(kAESKey_256), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_cbc_encrypt(kPlaintext, output, - sizeof(kPlaintext), &aes_key, aes_iv, AES_ENCRYPT)); - ASSERT_TRUE(check_test(kAESCBCCiphertext_256, output, sizeof(kAESCBCCiphertext_256), - "AES-CBC Encryption KAT for 256 bit key")); - ASSERT_EQ(approved, AWSLC_APPROVED); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); + ASSERT_TRUE( + AES_set_encrypt_key(kAESKey_256, 8 * sizeof(kAESKey_256), &aes_key) == 0); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, AES_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), + &aes_key, aes_iv, AES_ENCRYPT)); + EXPECT_EQ(Bytes(kAESCBCCiphertext_256), Bytes(output)); + EXPECT_EQ(approved, AWSLC_APPROVED); // AES-CBC Decryption KAT for 256 bit key. - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); - ASSERT_TRUE(AES_set_decrypt_key(kAESKey_256, 8 * sizeof(kAESKey_256), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_cbc_encrypt(kAESCBCCiphertext_256, output, - sizeof(kAESCBCCiphertext_256), &aes_key, aes_iv, AES_DECRYPT)); - ASSERT_TRUE(check_test(kPlaintext, output, sizeof(kPlaintext), - "AES-CBC Decryption KAT for 256 bit key")); - ASSERT_EQ(approved, AWSLC_APPROVED); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); + ASSERT_TRUE( + AES_set_decrypt_key(kAESKey_256, 8 * sizeof(kAESKey_256), &aes_key) == 0); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, AES_cbc_encrypt(kAESCBCCiphertext_256, output, + sizeof(kAESCBCCiphertext_256), &aes_key, aes_iv, + AES_DECRYPT)); + EXPECT_EQ(Bytes(kPlaintext), Bytes(output)); + EXPECT_EQ(approved, AWSLC_APPROVED); } TEST(ServiceIndicatorTest, AESCTR) { - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; AES_KEY aes_key; - uint8_t aes_iv[16]; - uint8_t output[256]; + uint8_t aes_iv[sizeof(kAESIV)]; + uint8_t output[sizeof(kPlaintext)]; unsigned num = 0; uint8_t ecount_buf[AES_BLOCK_SIZE]; // AES-CTR Encryption KAT - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); ASSERT_TRUE(AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_ctr128_encrypt(kPlaintext, output, - sizeof(kPlaintext), &aes_key, aes_iv, ecount_buf, &num)); - ASSERT_TRUE(check_test(kAESCTRCiphertext, output, sizeof(kAESCTRCiphertext), - "AES-CTR Encryption KAT")); - ASSERT_EQ(approved, AWSLC_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, AES_ctr128_encrypt(kPlaintext, output, sizeof(kPlaintext), + &aes_key, aes_iv, ecount_buf, &num)); + EXPECT_EQ(Bytes(kAESCTRCiphertext), Bytes(output)); + EXPECT_EQ(approved, AWSLC_APPROVED); // AES-CTR Decryption KAT - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_ctr128_encrypt(kAESCTRCiphertext, output, - sizeof(kAESCTRCiphertext), &aes_key, aes_iv, ecount_buf, &num)); - ASSERT_TRUE(check_test(kPlaintext, output, sizeof(kPlaintext), - "AES-CTR Decryption KAT")); - ASSERT_EQ(approved, AWSLC_APPROVED); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, + AES_ctr128_encrypt(kAESCTRCiphertext, output, sizeof(kAESCTRCiphertext), + &aes_key, aes_iv, ecount_buf, &num)); + EXPECT_EQ(Bytes(kPlaintext), Bytes(output)); + EXPECT_EQ(approved, AWSLC_APPROVED); // AES-CTR Encryption KAT for 192 bit key. - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); - ASSERT_TRUE(AES_set_encrypt_key(kAESKey_192, 8 * sizeof(kAESKey_192), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_ctr128_encrypt(kPlaintext, output, - sizeof(kPlaintext), &aes_key, aes_iv, ecount_buf, &num)); - ASSERT_TRUE(check_test(kAESCTRCiphertext_192, output, sizeof(kAESCTRCiphertext_192), - "AES-CTR Encryption KAT for 192 bit key")); - ASSERT_EQ(approved, AWSLC_APPROVED); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); + ASSERT_TRUE( + AES_set_encrypt_key(kAESKey_192, 8 * sizeof(kAESKey_192), &aes_key) == 0); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, AES_ctr128_encrypt(kPlaintext, output, sizeof(kPlaintext), + &aes_key, aes_iv, ecount_buf, &num)); + EXPECT_EQ(Bytes(kAESCTRCiphertext_192), Bytes(output)); + EXPECT_EQ(approved, AWSLC_APPROVED); // AES-CTR Decryption KAT for 192 bit key. - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_ctr128_encrypt(kAESCTRCiphertext_192, output, - sizeof(kAESCTRCiphertext_192), &aes_key, aes_iv, ecount_buf, &num)); - ASSERT_TRUE(check_test(kPlaintext, output, sizeof(kPlaintext), - "AES-CTR Decryption KAT for 192 bit key")); - ASSERT_EQ(approved, AWSLC_APPROVED); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, AES_ctr128_encrypt(kAESCTRCiphertext_192, output, + sizeof(kAESCTRCiphertext_192), &aes_key, + aes_iv, ecount_buf, &num)); + EXPECT_EQ(Bytes(kPlaintext), Bytes(output)); + EXPECT_EQ(approved, AWSLC_APPROVED); // AES-CTR Encryption KAT for 256 bit key. - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); - ASSERT_TRUE(AES_set_encrypt_key(kAESKey_256, 8 * sizeof(kAESKey_256), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_ctr128_encrypt(kPlaintext, output, - sizeof(kPlaintext), &aes_key, aes_iv, ecount_buf, &num)); - ASSERT_TRUE(check_test(kAESCTRCiphertext_256, output, sizeof(kAESCTRCiphertext_256), - "AES-CTR Encryption KAT for 256 bit key")); - ASSERT_EQ(approved, AWSLC_APPROVED); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); + ASSERT_TRUE( + AES_set_encrypt_key(kAESKey_256, 8 * sizeof(kAESKey_256), &aes_key) == 0); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, AES_ctr128_encrypt(kPlaintext, output, sizeof(kPlaintext), + &aes_key, aes_iv, ecount_buf, &num)); + EXPECT_EQ(Bytes(kAESCTRCiphertext_256), Bytes(output)); + EXPECT_EQ(approved, AWSLC_APPROVED); // AES-CTR Decryption KAT for 256 bit key. - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_ctr128_encrypt(kAESCTRCiphertext_256, output, - sizeof(kAESCTRCiphertext_256), &aes_key, aes_iv, ecount_buf, &num)); - ASSERT_TRUE(check_test(kPlaintext, output, sizeof(kPlaintext), - "AES-CTR Decryption KAT for 256 bit key")); - ASSERT_EQ(approved, AWSLC_APPROVED); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, AES_ctr128_encrypt(kAESCTRCiphertext_256, output, + sizeof(kAESCTRCiphertext_256), &aes_key, + aes_iv, ecount_buf, &num)); + EXPECT_EQ(Bytes(kPlaintext), Bytes(output)); + EXPECT_EQ(approved, AWSLC_APPROVED); } TEST(ServiceIndicatorTest, AESOFB) { - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; AES_KEY aes_key; uint8_t aes_iv[sizeof(kAESIV)]; - uint8_t output[256]; + uint8_t output[sizeof(kPlaintext)]; int num = 0; // AES-OFB Encryption KAT - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); ASSERT_TRUE(AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_ofb128_encrypt(kPlaintext, output, - sizeof(kPlaintext), &aes_key, aes_iv, &num)); - ASSERT_TRUE(check_test(kAESOFBCiphertext, output, sizeof(kAESOFBCiphertext), - "AES-OFB Encryption KAT")); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, AES_ofb128_encrypt(kPlaintext, output, sizeof(kPlaintext), + &aes_key, aes_iv, &num)); + EXPECT_EQ(Bytes(kAESOFBCiphertext), Bytes(output)); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); // AES-OFB Decryption KAT - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_ofb128_encrypt(kAESOFBCiphertext, output, - sizeof(kAESOFBCiphertext), &aes_key, aes_iv, &num)); - ASSERT_TRUE(check_test(kPlaintext, output, sizeof(kPlaintext), - "AES-OFB Decryption KAT")); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, + AES_ofb128_encrypt(kAESOFBCiphertext, output, sizeof(kAESOFBCiphertext), + &aes_key, aes_iv, &num)); + EXPECT_EQ(Bytes(kPlaintext), Bytes(output)); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); } TEST(ServiceIndicatorTest, AESCFB) { - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; AES_KEY aes_key; uint8_t aes_iv[sizeof(kAESIV)]; - uint8_t output[256]; + uint8_t output[sizeof(kPlaintext)]; int num = 0; // AES-CFB Encryption KAT - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); ASSERT_TRUE(AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_cfb128_encrypt(kPlaintext, output, - sizeof(kPlaintext), &aes_key, aes_iv, &num, AES_ENCRYPT)); - ASSERT_TRUE(check_test(kAESCFBCiphertext, output, sizeof(kAESCFBCiphertext), - "AES-CFB Encryption KAT")); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, AES_cfb128_encrypt(kPlaintext, output, sizeof(kPlaintext), + &aes_key, aes_iv, &num, AES_ENCRYPT)); + EXPECT_EQ(Bytes(kAESCFBCiphertext), Bytes(output)); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); // AES-CFB Decryption KAT - memcpy(aes_iv, kAESIV, sizeof(kAESIV)); - CALL_SERVICE_AND_CHECK_APPROVED(approved, AES_cfb128_encrypt(kAESCFBCiphertext, output, - sizeof(kAESCFBCiphertext), &aes_key, aes_iv, &num, AES_DECRYPT)); - ASSERT_TRUE(check_test(kPlaintext, output, sizeof(kPlaintext), - "AES-CFB Decryption KAT")); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + memcpy(aes_iv, kAESIV, sizeof(aes_iv)); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, + AES_cfb128_encrypt(kAESCFBCiphertext, output, sizeof(kAESCFBCiphertext), + &aes_key, aes_iv, &num, AES_DECRYPT)); + EXPECT_EQ(Bytes(kPlaintext), Bytes(output)); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); } TEST(ServiceIndicatorTest, AESKW) { - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; AES_KEY aes_key; - uint8_t output[256]; + uint8_t output[sizeof(kPlaintext) + 8]; size_t outlen; // AES-KW Encryption KAT ASSERT_TRUE(AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved, outlen = AES_wrap_key(&aes_key, nullptr, - output, kPlaintext, sizeof(kPlaintext))); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, outlen = AES_wrap_key(&aes_key, nullptr, output, kPlaintext, + sizeof(kPlaintext))); ASSERT_EQ(outlen, sizeof(kAESKWCiphertext)); - ASSERT_TRUE(check_test(kAESKWCiphertext, output, outlen, "AES-KW Encryption KAT")); - ASSERT_EQ(approved, AWSLC_APPROVED); + EXPECT_EQ(Bytes(kAESKWCiphertext), Bytes(output)); + EXPECT_EQ(approved, AWSLC_APPROVED); // AES-KW Decryption KAT ASSERT_TRUE(AES_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved,outlen = AES_unwrap_key(&aes_key, nullptr, - output, kAESKWCiphertext, sizeof(kAESKWCiphertext))); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, outlen = AES_unwrap_key(&aes_key, nullptr, output, + kAESKWCiphertext, + sizeof(kAESKWCiphertext))); ASSERT_EQ(outlen, sizeof(kPlaintext)); - ASSERT_TRUE(check_test(kPlaintext, output, outlen, "AES-KW Decryption KAT")); - ASSERT_EQ(approved, AWSLC_APPROVED); + EXPECT_EQ(Bytes(kPlaintext), Bytes(output, sizeof(kPlaintext))); + EXPECT_EQ(approved, AWSLC_APPROVED); } TEST(ServiceIndicatorTest, AESKWP) { - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; AES_KEY aes_key; - uint8_t output[256]; + uint8_t output[sizeof(kPlaintext) + 15]; size_t outlen; + // AES-KWP Encryption KAT - memset(output, 0, 256); ASSERT_TRUE(AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(AES_wrap_key_padded(&aes_key, - output, &outlen, sizeof(kPlaintext) + 15, kPlaintext, sizeof(kPlaintext)))); - ASSERT_TRUE(check_test(kAESKWPCiphertext, output, outlen, "AES-KWP Encryption KAT")); - ASSERT_EQ(approved, AWSLC_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(AES_wrap_key_padded(&aes_key, output, &outlen, sizeof(output), + kPlaintext, sizeof(kPlaintext)))); + EXPECT_EQ(Bytes(kAESKWPCiphertext), Bytes(output, outlen)); + EXPECT_EQ(approved, AWSLC_APPROVED); // AES-KWP Decryption KAT ASSERT_TRUE(AES_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) == 0); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(AES_unwrap_key_padded(&aes_key, - output, &outlen, sizeof(kAESKWPCiphertext), kAESKWPCiphertext, sizeof(kAESKWPCiphertext)))); - ASSERT_TRUE(check_test(kPlaintext, output, outlen, "AES-KWP Decryption KAT")); - ASSERT_EQ(approved, AWSLC_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(AES_unwrap_key_padded(&aes_key, output, &outlen, + sizeof(output), kAESKWPCiphertext, + sizeof(kAESKWPCiphertext)))); + EXPECT_EQ(Bytes(kPlaintext), Bytes(output, outlen)); + EXPECT_EQ(approved, AWSLC_APPROVED); } TEST(ServiceIndicatorTest, FFDH) { - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; // |DH_compute_key_padded| should be a non-approved service. - bssl::UniquePtr ffdhe2048_value(BN_new()); - bssl::UniquePtr dh(self_test_dh()); - ffdhe2048_value.get()->d = (BN_ULONG *)kFFDHE2048PublicValueData; - ffdhe2048_value.get()->width = OPENSSL_ARRAY_SIZE(kFFDHE2048PublicValueData); - ffdhe2048_value.get()->dmax = OPENSSL_ARRAY_SIZE(kFFDHE2048PublicValueData); - ffdhe2048_value.get()->neg = 0; - ffdhe2048_value.get()->flags |= BN_FLG_STATIC_DATA; - + bssl::UniquePtr dh(GetDH()); uint8_t dh_out[sizeof(kDHOutput)]; ASSERT_EQ(DH_size(dh.get()), static_cast(sizeof(dh_out))); - CALL_SERVICE_AND_CHECK_APPROVED(approved, - ASSERT_EQ(DH_compute_key_padded(dh_out, ffdhe2048_value.get(), dh.get()), - static_cast(sizeof(dh_out)))); - ASSERT_TRUE(check_test(kDHOutput, dh_out, sizeof(dh_out), "FFC DH")); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_EQ(DH_compute_key_padded( + dh_out, DH_get0_priv_key(dh.get()), dh.get()), + static_cast(sizeof(dh_out)))); + EXPECT_EQ(Bytes(kDHOutput), Bytes(dh_out)); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); } TEST(ServiceIndicatorTest, DRBG) { - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; CTR_DRBG_STATE drbg; - uint8_t output[256]; + uint8_t output[sizeof(kDRBGOutput)]; // Test running the DRBG interfaces and check |CTR_DRBG_generate| for approval // at the end since it indicates a service is being done. |CTR_DRBG_init| and // |CTR_DRBG_reseed| should not be approved, because the functions do not // indicate that a service has been fully completed yet. - // These DRBG functions are not directly accessible for external consumers - // however. - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(CTR_DRBG_init(&drbg, - kDRBGEntropy, kDRBGPersonalization, sizeof(kDRBGPersonalization)))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(CTR_DRBG_generate(&drbg, - output, sizeof(kDRBGOutput), kDRBGAD, sizeof(kDRBGAD)))); - ASSERT_EQ(approved, AWSLC_APPROVED); - ASSERT_TRUE(check_test(kDRBGOutput, output, sizeof(kDRBGOutput),"DBRG Generate KAT")); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(CTR_DRBG_init(&drbg, kDRBGEntropy, kDRBGPersonalization, + sizeof(kDRBGPersonalization)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(CTR_DRBG_generate(&drbg, output, sizeof(kDRBGOutput), kDRBGAD, + sizeof(kDRBGAD)))); + EXPECT_EQ(approved, AWSLC_APPROVED); + EXPECT_EQ(Bytes(kDRBGOutput), Bytes(output)); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(CTR_DRBG_reseed(&drbg, - kDRBGEntropy2, kDRBGAD, sizeof(kDRBGAD)))); - ASSERT_EQ(approved, AWSLC_NOT_APPROVED); - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(CTR_DRBG_generate(&drbg, - output, sizeof(kDRBGReseedOutput), kDRBGAD, sizeof(kDRBGAD)))); - ASSERT_EQ(approved, AWSLC_APPROVED); - ASSERT_TRUE(check_test(kDRBGReseedOutput, output, sizeof(kDRBGReseedOutput),"DRBG Reseed KAT")); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(CTR_DRBG_reseed(&drbg, kDRBGEntropy2, kDRBGAD, + sizeof(kDRBGAD)))); + EXPECT_EQ(approved, AWSLC_NOT_APPROVED); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + ASSERT_TRUE(CTR_DRBG_generate(&drbg, output, sizeof(kDRBGReseedOutput), + kDRBGAD, sizeof(kDRBGAD)))); + EXPECT_EQ(approved, AWSLC_APPROVED); + EXPECT_EQ(Bytes(kDRBGReseedOutput), Bytes(output)); - // Test approval of |RAND_bytes|, which is the only way for the consumer to - // indirectly interact with the DRBG functions. - CALL_SERVICE_AND_CHECK_APPROVED(approved, ASSERT_TRUE(RAND_bytes(output, sizeof(output)))); - ASSERT_EQ(approved, AWSLC_APPROVED); - CTR_DRBG_clear(&drbg); + CALL_SERVICE_AND_CHECK_APPROVED( + approved, ASSERT_TRUE(RAND_bytes(output, sizeof(output)))); + EXPECT_EQ(approved, AWSLC_APPROVED); } // Verifies that the awslc_version_string is as expected. @@ -2170,7 +2495,7 @@ TEST(ServiceIndicatorTest, AWSLCVersionString) { // will not indicate an approved state. TEST(ServiceIndicatorTest, BasicTest) { // Reset and check the initial state and counter. - int approved = AWSLC_NOT_APPROVED; + FIPSStatus approved = AWSLC_NOT_APPROVED; uint64_t before = FIPS_service_indicator_before_call(); ASSERT_EQ(before, (uint64_t)0); @@ -2179,28 +2504,26 @@ TEST(ServiceIndicatorTest, BasicTest) { uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH] = {0}; uint8_t output[256]; size_t out_len; - ASSERT_TRUE(EVP_AEAD_CTX_init(aead_ctx.get(), EVP_aead_aes_128_gcm_randnonce(), - kAESKey, sizeof(kAESKey), 0, nullptr)); - CALL_SERVICE_AND_CHECK_APPROVED(approved, EVP_AEAD_CTX_seal(aead_ctx.get(), - output, &out_len, sizeof(output), nullptr, 0, kPlaintext, sizeof(kPlaintext), nullptr, 0)); + ASSERT_TRUE(EVP_AEAD_CTX_init(aead_ctx.get(), + EVP_aead_aes_128_gcm_randnonce(), kAESKey, + sizeof(kAESKey), 0, nullptr)); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + EVP_AEAD_CTX_seal(aead_ctx.get(), output, &out_len, sizeof(output), + nullptr, 0, kPlaintext, sizeof(kPlaintext), nullptr, 0)); // Macro should return true, to ensure FIPS/Non-FIPS compatibility. ASSERT_EQ(approved, AWSLC_APPROVED); - // Approval check should also return true when not in FIPS mode. - uint64_t after = FIPS_service_indicator_after_call(); - ASSERT_EQ(after, (uint64_t)0); - ASSERT_TRUE(FIPS_service_indicator_check_approved(before, after)); - - // Call a non-approved service. ASSERT_TRUE(EVP_AEAD_CTX_init(aead_ctx.get(), EVP_aead_aes_128_gcm(), kAESKey, sizeof(kAESKey), 0, nullptr)); - CALL_SERVICE_AND_CHECK_APPROVED(approved, EVP_AEAD_CTX_seal(aead_ctx.get(), - output, &out_len, sizeof(output), nonce, EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()), - kPlaintext, sizeof(kPlaintext), nullptr, 0)); + CALL_SERVICE_AND_CHECK_APPROVED(approved, + EVP_AEAD_CTX_seal(aead_ctx.get(), output, &out_len, sizeof(output), nonce, + EVP_AEAD_nonce_length(EVP_aead_aes_128_gcm()), kPlaintext, + sizeof(kPlaintext), nullptr, 0)); ASSERT_EQ(approved, AWSLC_APPROVED); } + // Verifies that the awslc_version_string is as expected. // Since this is not running in FIPS mode it shouldn't end in FIPS // Update this when the AWS-LC version number is modified diff --git a/include/openssl/service_indicator.h b/include/openssl/service_indicator.h index f0adabec3e..30bb2a359f 100644 --- a/include/openssl/service_indicator.h +++ b/include/openssl/service_indicator.h @@ -10,9 +10,6 @@ extern "C" { #endif -#define AWSLC_APPROVED 1 -#define AWSLC_NOT_APPROVED 0 - // |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. @@ -28,18 +25,13 @@ OPENSSL_EXPORT uint64_t FIPS_service_indicator_after_call(void); OPENSSL_EXPORT const char* awslc_version_string(void); -// |FIPS_service_indicator_check_approved| is intended to take in the before and -// after counter values. It will return |AWSLC_APPROVED| if the approval check -// was successful, and |AWSLC_NOT_APPROVED| if otherwise. -// -// Service indicator calls should not be used in non-FIPS builds. However, if -// used, the direct check to |FIPS_service_indicator_check_approved| -// will always indicate |AWSLC_APPROVED| in non-FIPS builds. -// It is recommended to use the macro |CALL_SERVICE_AND_CHECK_APPROVED| though, -// which will also always return |AWSLC_APPROVED| in non-FIPS builds. -OPENSSL_EXPORT int FIPS_service_indicator_check_approved(uint64_t before, uint64_t after); +enum FIPSStatus { + AWSLC_NOT_APPROVED = 0, + AWSLC_APPROVED = 1, +}; #if defined(AWSLC_FIPS) + #define AWSLC_MODE_STRING "AWS-LC FIPS " // This macro provides a bundled way to do an approval check and run the service. @@ -53,7 +45,7 @@ OPENSSL_EXPORT int FIPS_service_indicator_check_approved(uint64_t before, uint64 int before = FIPS_service_indicator_before_call(); \ func; \ int after = FIPS_service_indicator_after_call(); \ - if (FIPS_service_indicator_check_approved(before, after)) { \ + if (before != after) { \ (approved) = AWSLC_APPROVED; \ } \ } \