Skip to content

Commit

Permalink
Take in BoringSSL service indicator improvements (#564)
Browse files Browse the repository at this point in the history
This PR takes in the service indicator improvements BoringSSL
made. 
Most of the changes were taken except:
* AWS-LC returns NOT_APPROVED for SHA-512/256. This is because
we have not gone through FIPS validation for algorithms
involving SHA-512/256, but we can expect to do so within the
next round of FIPS.
* kEVPKeyGenShouldCallFIPSFunctions, kCurveSecp256k1Supported,
kEVPDeriveSetsServiceIndicator are set to true. BoringSSL was
nice enough to use these bool to help us keep some of our
existing AWS-LC specific tests. These are set to false for
BoringSSL.
* We kept the original behavior for the service indicator macro
CALL_SERVICE_AND_CHECK_APPROVED. The new version BoringSSL
introduced was only compatibile with C++ and we have
interoperability concerns for FIPS consumers building with C
packages.
  • Loading branch information
samuel40791765 authored Aug 8, 2022
1 parent 07f270f commit 14a4d50
Show file tree
Hide file tree
Showing 10 changed files with 1,793 additions and 1,525 deletions.
10 changes: 5 additions & 5 deletions crypto/fipsmodule/aes/key_wrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
19 changes: 7 additions & 12 deletions crypto/fipsmodule/aes/mode_wrappers.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down
68 changes: 37 additions & 31 deletions crypto/fipsmodule/cipher/cipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
}

Expand Down
32 changes: 11 additions & 21 deletions crypto/fipsmodule/cipher/e_aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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 {
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down
8 changes: 4 additions & 4 deletions crypto/fipsmodule/evp/digestsign.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down
Loading

0 comments on commit 14a4d50

Please sign in to comment.