Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions crypto/cipher_extra/aead_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include "../fipsmodule/cipher/internal.h"
#include "../internal.h"
#include "./internal.h"
#include "../test/abi_test.h"
#include "../test/file_test.h"
#include "../test/test_util.h"
Expand Down Expand Up @@ -1263,3 +1264,114 @@ TEST(AEADTest, AEADAES256GCMDetIVGen) {
EXPECT_TRUE(EVP_AEAD_get_iv_from_ipv4_nanosecs(ip_address, fake_time, out));
EXPECT_EQ(Bytes(out, sizeof(out)), Bytes(expected, sizeof(expected)));
}

static int awslc_encrypt(EVP_AEAD_CTX *ctx, uint8_t *nonce,
uint8_t *ct, uint8_t *pt) {
size_t ct_len = 0;
GTEST_LOG_(INFO) << "awslc_encrypt: Ctx.State Location: "
<< &ctx->state;
if (EVP_AEAD_CTX_seal(ctx, ct, &ct_len, 32, nonce, 12, pt, 16, NULL, 0) !=
1) {
return 1;
}

return 0;
}

static int awslc_decrypt(const EVP_AEAD *cipher, uint8_t ct[32], uint8_t *key,
size_t key_len, uint8_t nonce[12], uint8_t pt[16]) {

EVP_AEAD_CTX ctx;
size_t pt_len = 0;

EVP_AEAD_CTX_zero(&ctx);
if (EVP_AEAD_CTX_init(&ctx, cipher, key, key_len, 16, NULL) != 1) {
return 1;
}
GTEST_LOG_(INFO) << "awslc_decrypt: Ctx.State Location: " << &ctx.state;

if (EVP_AEAD_CTX_open(&ctx, pt, &pt_len, 16, nonce, 12, ct, 32, NULL, 0) !=
1) {
return 1;
}

return 0;
}

TEST(AEADTest, TestGCMSIV128Change16Alignment) {
uint8_t key[16] = {0};
uint8_t nonce[12] = {0};
uint8_t pt[16] = {0};
uint8_t ct[32] = {0};
EVP_AEAD_CTX* encrypt_ctx_128 = (EVP_AEAD_CTX*)malloc(sizeof(EVP_AEAD_CTX) + 8);

const EVP_AEAD *cipher_128 = EVP_aead_aes_128_gcm_siv();

EVP_AEAD_CTX_zero(encrypt_ctx_128);
ASSERT_TRUE(EVP_AEAD_CTX_init(encrypt_ctx_128, cipher_128, key, 16, 16, NULL))
<< ERR_error_string(ERR_get_error(), NULL);
ASSERT_FALSE(awslc_encrypt(encrypt_ctx_128, nonce, ct, pt))
<< ERR_error_string(ERR_get_error(), NULL);
ASSERT_FALSE(awslc_decrypt(cipher_128, ct, key, 16, nonce, pt))
<< ERR_error_string(ERR_get_error(), NULL);

GTEST_LOG_(INFO) << "Orig. Ctx.State Location: " << &encrypt_ctx_128->state;
EVP_AEAD_CTX *moved_encrypt_ctx_128 =
(EVP_AEAD_CTX *)(((uint8_t *)encrypt_ctx_128) + 8);
memmove(moved_encrypt_ctx_128, encrypt_ctx_128, sizeof(EVP_AEAD_CTX));
GTEST_LOG_(INFO) << "Moved Ctx.State Location: "
<< &moved_encrypt_ctx_128->state;

if (awslc_encrypt(moved_encrypt_ctx_128, nonce, ct, pt) != 1) {
if (x86_64_assembly_implementation_FOR_TESTING()) {
FAIL() << "Expected failure in awslc_encrypt";
}
} else {
if (!x86_64_assembly_implementation_FOR_TESTING()) {
FAIL() << "Failure in awslc_encrypt";
}
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_R_CIPHER_LIB, ERR_GET_LIB(err));
EXPECT_EQ(CIPHER_R_ALIGNMENT_CHANGED, ERR_GET_REASON(err));
}
free(encrypt_ctx_128);
}

TEST(AEADTest, TestGCMSIV256Change16Alignment) {
uint8_t nonce[12] = {0};
uint8_t key[32] = {0};
uint8_t pt[16] = {0};
uint8_t ct[32] = {0};
EVP_AEAD_CTX* encrypt_ctx_256 = (EVP_AEAD_CTX*)malloc(sizeof(EVP_AEAD_CTX) + 8);

const EVP_AEAD *cipher_256 = EVP_aead_aes_256_gcm_siv();

EVP_AEAD_CTX_zero(encrypt_ctx_256);
ASSERT_TRUE(EVP_AEAD_CTX_init(encrypt_ctx_256, cipher_256, key, 32, 16, NULL))
<< ERR_error_string(ERR_get_error(), NULL);
ASSERT_FALSE(awslc_encrypt(encrypt_ctx_256, nonce, ct, pt))
<< ERR_error_string(ERR_get_error(), NULL);
ASSERT_FALSE(awslc_decrypt(cipher_256, ct, key, 32, nonce, pt))
<< ERR_error_string(ERR_get_error(), NULL);

GTEST_LOG_(INFO) << "Orig. Ctx.State Location: " << &encrypt_ctx_256->state;
EVP_AEAD_CTX *moved_encrypt_ctx_256 =
(EVP_AEAD_CTX *)(((uint8_t *)encrypt_ctx_256) + 8);
memmove(moved_encrypt_ctx_256, encrypt_ctx_256, sizeof(EVP_AEAD_CTX));
GTEST_LOG_(INFO) << "Moved Ctx.State Location: "
<< &moved_encrypt_ctx_256->state;

if (awslc_encrypt(moved_encrypt_ctx_256, nonce, ct, pt) != 1) {
if (x86_64_assembly_implementation_FOR_TESTING()) {
FAIL() << "Expected failure in awslc_encrypt";
}
} else {
if (!x86_64_assembly_implementation_FOR_TESTING()) {
FAIL() << "Failure in awslc_encrypt";
}
uint32_t err = ERR_get_error();
EXPECT_EQ(ERR_R_CIPHER_LIB, ERR_GET_LIB(err));
EXPECT_EQ(CIPHER_R_ALIGNMENT_CHANGED, ERR_GET_REASON(err));
}
free(encrypt_ctx_256);
}
32 changes: 30 additions & 2 deletions crypto/cipher_extra/e_aesgcmsiv.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include "../fipsmodule/cipher/internal.h"
#include "../internal.h"
#include "./internal.h"


#define EVP_AEAD_AES_GCM_SIV_NONCE_LEN 12
Expand Down Expand Up @@ -53,8 +54,11 @@ static struct aead_aes_gcm_siv_asm_ctx *asm_ctx_from_ctx(
const EVP_AEAD_CTX *ctx) {
// ctx->state must already be 8-byte aligned. Thus, at most, we may need to
// add eight to align it to 16 bytes.
const uintptr_t offset = ((uintptr_t)&ctx->state) & 8;
return (struct aead_aes_gcm_siv_asm_ctx *)(&ctx->state.opaque[offset]);
const uintptr_t actual_offset = ((uintptr_t)&ctx->state) & 8;
if(ctx->state_offset != actual_offset) {
return NULL;
}
return (struct aead_aes_gcm_siv_asm_ctx *)(&ctx->state.opaque[actual_offset]);
}

// aes128gcmsiv_aes_ks writes an AES-128 key schedule for |key| to
Expand Down Expand Up @@ -85,7 +89,12 @@ static int aead_aes_gcm_siv_asm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
return 0;
}

ctx->state_offset = ((uintptr_t)&ctx->state) & 8;
struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx = asm_ctx_from_ctx(ctx);
if(gcm_siv_ctx == NULL) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INITIALIZATION_ERROR);
return 0;
}
assert((((uintptr_t)gcm_siv_ctx) & 15) == 0);

if (key_bits == 128) {
Expand Down Expand Up @@ -332,6 +341,10 @@ static int aead_aes_gcm_siv_asm_seal_scatter(
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
const struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx = asm_ctx_from_ctx(ctx);
if(gcm_siv_ctx == NULL) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_ALIGNMENT_CHANGED);
return 0;
}
const uint64_t in_len_64 = in_len;
const uint64_t ad_len_64 = ad_len;

Expand Down Expand Up @@ -419,6 +432,10 @@ static int aead_aes_gcm_siv_asm_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
}

const struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx = asm_ctx_from_ctx(ctx);
if(gcm_siv_ctx == NULL) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_ALIGNMENT_CHANGED);
return 0;
}
const size_t plaintext_len = in_len - EVP_AEAD_AES_GCM_SIV_TAG_LEN;
const uint8_t *const given_tag = in + plaintext_len;

Expand Down Expand Up @@ -849,10 +866,21 @@ const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void) {
return &aead_aes_256_gcm_siv;
}

int x86_64_assembly_implementation_FOR_TESTING(void) {
if (CRYPTO_is_AVX_capable() && CRYPTO_is_AESNI_capable()) {
return 1;
}
return 0;
}

#else

const EVP_AEAD *EVP_aead_aes_128_gcm_siv(void) { return &aead_aes_128_gcm_siv; }

const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void) { return &aead_aes_256_gcm_siv; }

int x86_64_assembly_implementation_FOR_TESTING(void) {
return 0;
}

#endif // AES_GCM_SIV_ASM
4 changes: 3 additions & 1 deletion crypto/cipher_extra/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
extern "C" {
#endif

OPENSSL_EXPORT int x86_64_assembly_implementation_FOR_TESTING(void);

#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
!defined(MY_ASSEMBLER_IS_TOO_OLD_FOR_AVX) && !defined(AWSLC_FIPS)
#define AES_CBC_HMAC_SHA_STITCH
Expand Down Expand Up @@ -149,7 +151,7 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
const uint8_t *mac_secret,
unsigned mac_secret_length);

// EVP_tls_cbc_digest_record_sha256 performs the same functionality of
// EVP_tls_cbc_digest_record_sha256 performs the same functionality of
// EVP_tls_cbc_digest_record except it internally calls SHA256 instead of SHA1.
int EVP_tls_cbc_digest_record_sha256(const EVP_MD *md, uint8_t *md_out,
size_t *md_out_size, const uint8_t header[13],
Expand Down
1 change: 1 addition & 0 deletions include/openssl/aead.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ union evp_aead_ctx_st_state {
struct evp_aead_ctx_st {
const EVP_AEAD *aead;
union evp_aead_ctx_st_state state;
uint8_t state_offset;
// tag_len may contain the actual length of the authentication tag if it is
// known at initialization time.
uint8_t tag_len;
Expand Down
1 change: 1 addition & 0 deletions include/openssl/cipher.h
Original file line number Diff line number Diff line change
Expand Up @@ -709,5 +709,6 @@ BSSL_NAMESPACE_END
#define CIPHER_R_XTS_DATA_UNIT_IS_TOO_LARGE 139
#define CIPHER_R_CTRL_OPERATION_NOT_PERFORMED 140
#define CIPHER_R_SERIALIZATION_INVALID_EVP_AEAD_CTX 141
#define CIPHER_R_ALIGNMENT_CHANGED 142

#endif // OPENSSL_HEADER_CIPHER_H