Add AES-GCM AEADs with internal nonce generation.

For FIPS reasons, one might wish to ensure that a random AES-GCM nonce
was generated entirely within the FIPS module. If so, then these are the
AEADs for you.

Change-Id: Ic2b7864b089f446401f700d7d55bfa6336c61e23
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/43686
Commit-Queue: Adam Langley <alangley@gmail.com>
Reviewed-by: David Benjamin <davidben@google.com>
chromium-5359
Adam Langley 4 years ago committed by Adam Langley
parent d5b2b17728
commit 83a3f462cf
  1. 43
      crypto/cipher_extra/aead_test.cc
  2. 30
      crypto/cipher_extra/test/aes_128_gcm_randnonce_tests.txt
  3. 30
      crypto/cipher_extra/test/aes_256_gcm_randnonce_tests.txt
  4. 182
      crypto/fipsmodule/cipher/e_aes.c
  5. 24
      include/openssl/aead.h
  6. 2
      sources.cmake

@ -40,6 +40,10 @@ constexpr uint32_t kLimitedImplementation = 1 << 0;
constexpr uint32_t kCanTruncateTags = 1 << 1; constexpr uint32_t kCanTruncateTags = 1 << 1;
// kVariableNonce indicates that the AEAD supports a variable-length nonce. // kVariableNonce indicates that the AEAD supports a variable-length nonce.
constexpr uint32_t kVariableNonce = 1 << 2; constexpr uint32_t kVariableNonce = 1 << 2;
// kNondeterministic indicates that the AEAD performs randomised encryption thus
// one cannot assume that encrypting the same data will result in the same
// ciphertext.
constexpr uint32_t kNondeterministic = 1 << 7;
// RequiresADLength encodes an AD length requirement into flags. // RequiresADLength encodes an AD length requirement into flags.
constexpr uint32_t RequiresADLength(size_t length) { constexpr uint32_t RequiresADLength(size_t length) {
@ -58,6 +62,16 @@ constexpr size_t RequiredADLength(uint32_t flags) {
return (flags >> 3) & 0xf; return (flags >> 3) & 0xf;
} }
constexpr uint32_t RequiresMinimumTagLength(size_t length) {
// See above for statically checking the size at compile time with future C++
// versions.
return (length & 0xf) << 8;
}
constexpr size_t MinimumTagLength(uint32_t flags) {
return ((flags >> 8) & 0xf) == 0 ? 1 : ((flags >> 8) & 0xf);
}
struct KnownAEAD { struct KnownAEAD {
const char name[40]; const char name[40];
const EVP_AEAD *(*func)(void); const EVP_AEAD *(*func)(void);
@ -87,6 +101,14 @@ static const struct KnownAEAD kAEADs[] = {
{"AES_256_GCM_SIV", EVP_aead_aes_256_gcm_siv, "aes_256_gcm_siv_tests.txt", {"AES_256_GCM_SIV", EVP_aead_aes_256_gcm_siv, "aes_256_gcm_siv_tests.txt",
0}, 0},
{"AES_128_GCM_RandomNonce", EVP_aead_aes_128_gcm_randnonce,
"aes_128_gcm_randnonce_tests.txt",
kNondeterministic | kCanTruncateTags | RequiresMinimumTagLength(13)},
{"AES_256_GCM_RandomNonce", EVP_aead_aes_256_gcm_randnonce,
"aes_256_gcm_randnonce_tests.txt",
kNondeterministic | kCanTruncateTags | RequiresMinimumTagLength(13)},
{"ChaCha20Poly1305", EVP_aead_chacha20_poly1305, {"ChaCha20Poly1305", EVP_aead_chacha20_poly1305,
"chacha20_poly1305_tests.txt", kCanTruncateTags}, "chacha20_poly1305_tests.txt", kCanTruncateTags},
@ -189,7 +211,8 @@ TEST_P(PerAEADTest, TestVector) {
ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_seal)); ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_seal));
std::vector<uint8_t> out(in.size() + EVP_AEAD_max_overhead(aead())); std::vector<uint8_t> out(in.size() + EVP_AEAD_max_overhead(aead()));
if (!t->HasAttribute("NO_SEAL")) { if (!t->HasAttribute("NO_SEAL") &&
!(GetParam().flags & kNondeterministic)) {
size_t out_len; size_t out_len;
ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(), ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
nonce.data(), nonce.size(), in.data(), nonce.data(), nonce.size(), in.data(),
@ -269,7 +292,8 @@ TEST_P(PerAEADTest, TestExtraInput) {
"crypto/cipher_extra/test/" + std::string(aead_config.test_vectors); "crypto/cipher_extra/test/" + std::string(aead_config.test_vectors);
FileTestGTest(test_vectors.c_str(), [&](FileTest *t) { FileTestGTest(test_vectors.c_str(), [&](FileTest *t) {
if (t->HasAttribute("NO_SEAL") || if (t->HasAttribute("NO_SEAL") ||
t->HasAttribute("FAILS")) { t->HasAttribute("FAILS") ||
(aead_config.flags & kNondeterministic)) {
t->SkipCurrent(); t->SkipCurrent();
return; return;
} }
@ -337,7 +361,8 @@ TEST_P(PerAEADTest, TestVectorScatterGather) {
std::vector<uint8_t> out(in.size()); std::vector<uint8_t> out(in.size());
std::vector<uint8_t> out_tag(EVP_AEAD_max_overhead(aead())); std::vector<uint8_t> out_tag(EVP_AEAD_max_overhead(aead()));
if (!t->HasAttribute("NO_SEAL")) { if (!t->HasAttribute("NO_SEAL") &&
!(aead_config.flags & kNondeterministic)) {
size_t out_tag_len; size_t out_tag_len;
ASSERT_TRUE(EVP_AEAD_CTX_seal_scatter( ASSERT_TRUE(EVP_AEAD_CTX_seal_scatter(
ctx.get(), out.data(), out_tag.data(), &out_tag_len, out_tag.size(), ctx.get(), out.data(), out_tag.data(), &out_tag_len, out_tag.size(),
@ -469,9 +494,10 @@ TEST_P(PerAEADTest, TruncatedTags) {
const size_t nonce_len = EVP_AEAD_nonce_length(aead()); const size_t nonce_len = EVP_AEAD_nonce_length(aead());
ASSERT_GE(sizeof(nonce), nonce_len); ASSERT_GE(sizeof(nonce), nonce_len);
const size_t tag_len = MinimumTagLength(GetParam().flags);
bssl::ScopedEVP_AEAD_CTX ctx; bssl::ScopedEVP_AEAD_CTX ctx;
ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), aead(), key, key_len, ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), aead(), key, key_len,
1 /* one byte tag */, NULL /* ENGINE */)); tag_len, NULL /* ENGINE */));
const uint8_t plaintext[1] = {'A'}; const uint8_t plaintext[1] = {'A'};
@ -492,7 +518,7 @@ TEST_P(PerAEADTest, TruncatedTags) {
const size_t overhead_used = ciphertext_len - sizeof(plaintext); const size_t overhead_used = ciphertext_len - sizeof(plaintext);
const size_t expected_overhead = const size_t expected_overhead =
1 + EVP_AEAD_max_overhead(aead()) - EVP_AEAD_max_tag_len(aead()); tag_len + EVP_AEAD_max_overhead(aead()) - EVP_AEAD_max_tag_len(aead());
EXPECT_EQ(overhead_used, expected_overhead) EXPECT_EQ(overhead_used, expected_overhead)
<< "AEAD is probably ignoring request to truncate tags."; << "AEAD is probably ignoring request to truncate tags.";
@ -578,8 +604,11 @@ TEST_P(PerAEADTest, AliasedBuffers) {
ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), in, &out_len, ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), in, &out_len,
sizeof(kPlaintext) + max_overhead, nonce.data(), sizeof(kPlaintext) + max_overhead, nonce.data(),
nonce_len, in, sizeof(kPlaintext), nullptr, 0)); nonce_len, in, sizeof(kPlaintext), nullptr, 0));
EXPECT_EQ(Bytes(valid_encryption.data(), valid_encryption_len),
Bytes(in, out_len)); if (!(GetParam().flags & kNondeterministic)) {
EXPECT_EQ(Bytes(valid_encryption.data(), valid_encryption_len),
Bytes(in, out_len));
}
OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len); OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len);
ASSERT_TRUE(EVP_AEAD_CTX_open(ctx.get(), in, &out_len, valid_encryption_len, ASSERT_TRUE(EVP_AEAD_CTX_open(ctx.get(), in, &out_len, valid_encryption_len,

@ -0,0 +1,30 @@
# These tests are versions of the tests from the corresponding AES-GCM test
# file, but with the nonce appended to the tag.
KEY: d480429666d48b400633921c5407d1d1
NONCE:
IN:
AD:
CT:
TAG: 7d7daf44850921a34e636b01adeb104f3388c676dc754acfa66e172a
KEY: 3881e7be1bb3bbcaff20bdb78e5d1b67
NONCE:
IN: 0a2714aa7d
AD: c60c64bbf7
CT: 5626f96ecb
TAG: ff4c4f1d92b0abb1d0820833d9eb83c7dcf5b7ae2d7552e2297fcfa9
KEY: ea4f6f3c2fed2b9dd9708c2e721ae00f
NONCE:
IN: 8d6c08446cb10d9a2075
AD: 5c65d4f261d2c54ffe6a
CT: 0f51f7a83c5b5aa796b9
TAG: 70259cddfe8f9a15a5c5eb485af578fbf975809ddb5172382745634f
KEY: 31d93fd51c2d6450cf35d9edd71413f4
NONCE:
IN: e78eba6c58f93cc2374932fc21e54f695f2daeda3bd1e0121a77d178e3bf5c0e824a99042e8f2522df829d014e4d35a756780e8c07f53ca8fb78db6fb76754ad461665051c4572b2514804d0a9cbae1a1a013b796565eee13a7832ab8834b8406b1185332552d38754dde2344ff4f6e4823390964ba2dc43de136f2235b1d919e0f4ad60813d30f0ac1dad35abe3bee9479337c7b430841d2c722f12aeaf931cedd8a82053f697fff8d07f0af6013da7da58a5dfcf45561943e7ccdfd8d11fbe96a68a5a27982e47346500c0284caf8e6b63c6621e80503a7365d6693dc9a249093dc45221cfd88562e25910034c2c123e44e3b09d8a8a15547285d2596b98c7a0ee9d10b2cdb032d08a6caee1212420b6854181a583c15e046aa202dd
AD: a4fdd42aad5475ffc1b122170024486406033c8640233cd9b23c286fdd40c5b69eee39cfbf965f7a10c73663f9804e6821c4f62980f8362a580bab446325b009a004b60b1dbd12566b55b42e58d8037d86c1050cd6ecaaac2fb0ef616a15bc5bcd8252fd459165795c500bbb2fb1476e5cfef9549db733be65bde391c810d099e3745a2cc7a94debe1f4ff6653b338123ef7d2f9a602bc9a4bbe757a63f932a802014f2f06c6688faf14332a355b1025f33687124399f55b6a5adb4864727ec6c5334c41d78d1463400925f6c29c0f611f35c9640045a740dad5b4f0dcb632e7f9a3478b526aa9f97cd9f8d3ad094b7922890e7b6d9c67fcc4f747d04ddcd115fba0a8f0433c6fb1bf6011a9cd153f866c76b26d427a25aebc60d10540
CT: 8d668fb50efda82552aeb5d075ff3977c37929d73f6639289e7c6da8c89c664df80b2387e788d12398d62d3c0ed2f9f918010d41021c464d54f016c4e10e85e29ba3a45793df2ebd6cdf30045363434387bb0d20439f4986e6eb7ae9fd85fe776f7b8035025624c2413ca8491cc6e79fe901b9c40ff3a0e37a7c7e88b56de4fee65861865162821e046846d253982e4ecd17bd26214b0923a4297d4ed9423395d856940829ca5ee74488c3b4d8aa3c5ceade17d8a3f2e45d3ba91360ac1c76d6a29f8243bf49c1d75aa41ba239fa6f3b123e198ba799e3b70c674607c5371894800954eda0264b3b82606433f71371dabc5f1fb3d703232533662920a241f613c38d16b0bad24f4aa3b336af89cdcd2f371e1bed7aaa47c56d17100a01
TAG: 594ee5c93636cfb5fde940e3d561440a28f6f0c288c9f92e80252e1e

@ -0,0 +1,30 @@
# These tests are versions of the tests from the corresponding AES-GCM test
# file, but with the nonce appended to the tag.
KEY: e5ac4a32c67e425ac4b143c83c6f161312a97d88d634afdf9f4da5bd35223f01
NONCE:
IN:
AD:
CT:
TAG: d7cba289d6d19a5af45dc13857016bac5bf11a0951f0bfc7ea5c9e58
KEY: 73ad7bbbbc640c845a150f67d058b279849370cd2c1f3c67c4dd6c869213e13a
NONCE:
IN: f0535fe211
AD: e91428be04
CT: e9b8a896da
TAG: 9115ed79f26a030c14947b3e454db9e7a330a184fc245812f4820caa
KEY: 80e2e561886eb2a953cf923aaac1653ed2db0111ee62e09cb20d9e2652bd3476
NONCE:
IN: 96669d2d3542a4d49c7c
AD: e51e5bce7cbceb660399
CT: 4521953e7d39497e4563
TAG: 2083e3c0d84d663066bbe2961b08dcf75daf201589654da8884c3c68
KEY: 31dbefe589b661af00a6fbad426e013f30f448c763f957bbcbaf9c09764f4a95
NONCE:
IN: 908bd801b70d85085dd480e1207a4a4b7ef179dac495a9befb16afe5adf7cb6f6d734882e6e96f587d38bfc080341dc8d5428a5fe3498b9d5faa497f60646bcb1155d2342f6b26381795daeb261d4ab1415f35c6c8ac9c8e90ea34823122df25c6ddae365cc66d92fc2fe2941f60895e00233b2e5968b01e2811c8c6f7a0a229f1c301a72715bd5c35234c1be81ef7d5cc2779e146314d3783a7aa72d87a8f107654b93cb66e3648c26fc9e4a2f0378fa178c586d096092f6a80e2e03708da72d6e4d7316c2384a522459a4ad369c82d192f6f695b0d90fcc47c6f86b8bbc6f2f4ea303aa64f5ce8b8710da62482147bcc29c8238116549256a7a011fd9c78bbb8c40e278740dc156c2cc99c3591fec2918cdeb5240fb428
AD: 5a32d7044f003b2ffefffe5896933f4d8d64909fa03e321a1bdf063099b9f89752d72e877291d8da12340c5dd570d7d42984ffab5177824fc5483b4faf488504e6822e371dca9af541c6a97312b9cbf341b4198b0902cd2985ac10a8b5b5fe9691bb29a88344f863c980e4e871a72a8b74f92eef68c176e9d2ef037898ff567298e186af52ec62eb7429a8004ac46b945678b82859396d36d388ec3d67653aec35cf1da2684bbc6c78a5f9e3ce1b355af3b207f64e0fa73501c5d48a14638d0906c87eaa876debcf1a532c1475d80ed3d4b96458d2236eb9f67988863bc6d5c16b96b93d898683d248d7bc601b5035fc365481b89465e37a8f7dd64635e19a0282639cecde72c6b1638e0aa6e56f9c00d031cdadc59ce37e
CT: aeab9db30a579ca54195e54a9e6c787f40100c6d12ceee35643f36ae45f618cc9bb66aa4c0fae0ec2686cb4101a5b23a46877460c7e020b38b0d8d1f533ecfa99df03d346bc854a578276d7d5685ad1fb03655683a64aae4159c9efa6781f053057e0811226c7c533967a94587f4025353b28cc3a2ce5763783b4c31e7818b8ad9195bc03be8f294f9f6ceac578f9d30b22b1f5a68d647d46cf6db4a9c3a8a5c06fa97c9efb4578f501ea96db1f40942e3f24c44a7e4070a6b931c39947d9692930b67767357015de51a39e46fff94b6019e4bc1ad9d216a571ba0dc88859c49d2c487ca657384e49b4d382d86a60c8d5195320909c4e82fc077a3b22bd4eccf0f067e66ec78eed642b2d16f0f304f60f1d9ba69e205c982
TAG: 17ca09e3084504fc22e914ee28312c8e147fe99bba0f606c57242314

@ -933,21 +933,19 @@ static int aead_aes_gcm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
static void aead_aes_gcm_cleanup(EVP_AEAD_CTX *ctx) {} static void aead_aes_gcm_cleanup(EVP_AEAD_CTX *ctx) {}
static int aead_aes_gcm_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out, static int aead_aes_gcm_seal_scatter_impl(
uint8_t *out_tag, size_t *out_tag_len, const struct aead_aes_gcm_ctx *gcm_ctx,
size_t max_out_tag_len, uint8_t *out, uint8_t *out_tag, size_t *out_tag_len, size_t max_out_tag_len,
const uint8_t *nonce, size_t nonce_len, const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len, const uint8_t *in, size_t in_len,
const uint8_t *extra_in, const uint8_t *extra_in, size_t extra_in_len,
size_t extra_in_len, const uint8_t *ad, size_t ad_len,
const uint8_t *ad, size_t ad_len) { size_t tag_len) {
struct aead_aes_gcm_ctx *gcm_ctx = (struct aead_aes_gcm_ctx *) &ctx->state; if (extra_in_len + tag_len < tag_len) {
if (extra_in_len + ctx->tag_len < ctx->tag_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
return 0; return 0;
} }
if (max_out_tag_len < extra_in_len + ctx->tag_len) { if (max_out_tag_len < extra_in_len + tag_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0; return 0;
} }
@ -991,18 +989,35 @@ static int aead_aes_gcm_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out,
} }
} }
CRYPTO_gcm128_tag(&gcm, out_tag + extra_in_len, ctx->tag_len); CRYPTO_gcm128_tag(&gcm, out_tag + extra_in_len, tag_len);
*out_tag_len = ctx->tag_len + extra_in_len; *out_tag_len = tag_len + extra_in_len;
return 1; return 1;
} }
static int aead_aes_gcm_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out, static int aead_aes_gcm_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out,
const uint8_t *nonce, size_t nonce_len, uint8_t *out_tag, size_t *out_tag_len,
const uint8_t *in, size_t in_len, size_t max_out_tag_len,
const uint8_t *in_tag, size_t in_tag_len, const uint8_t *nonce, size_t nonce_len,
const uint8_t *ad, size_t ad_len) { const uint8_t *in, size_t in_len,
struct aead_aes_gcm_ctx *gcm_ctx = (struct aead_aes_gcm_ctx *) &ctx->state; const uint8_t *extra_in,
size_t extra_in_len,
const uint8_t *ad, size_t ad_len) {
const struct aead_aes_gcm_ctx *gcm_ctx =
(const struct aead_aes_gcm_ctx *)&ctx->state;
return aead_aes_gcm_seal_scatter_impl(
gcm_ctx, out, out_tag, out_tag_len, max_out_tag_len, nonce, nonce_len, in,
in_len, extra_in, extra_in_len, ad, ad_len, ctx->tag_len);
}
static int aead_aes_gcm_open_gather_impl(const struct aead_aes_gcm_ctx *gcm_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,
size_t tag_len) {
uint8_t tag[EVP_AEAD_AES_GCM_TAG_LEN]; uint8_t tag[EVP_AEAD_AES_GCM_TAG_LEN];
if (nonce_len == 0) { if (nonce_len == 0) {
@ -1010,7 +1025,7 @@ static int aead_aes_gcm_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 0; return 0;
} }
if (in_tag_len != ctx->tag_len) { if (in_tag_len != tag_len) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0; return 0;
} }
@ -1037,8 +1052,8 @@ static int aead_aes_gcm_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
} }
} }
CRYPTO_gcm128_tag(&gcm, tag, ctx->tag_len); CRYPTO_gcm128_tag(&gcm, tag, tag_len);
if (CRYPTO_memcmp(tag, in_tag, ctx->tag_len) != 0) { if (CRYPTO_memcmp(tag, in_tag, tag_len) != 0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0; return 0;
} }
@ -1046,6 +1061,17 @@ static int aead_aes_gcm_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 1; return 1;
} }
static int aead_aes_gcm_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) {
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);
}
DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_128_gcm) { DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_128_gcm) {
memset(out, 0, sizeof(EVP_AEAD)); memset(out, 0, sizeof(EVP_AEAD));
@ -1091,6 +1117,116 @@ DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_256_gcm) {
out->open_gather = aead_aes_gcm_open_gather; out->open_gather = aead_aes_gcm_open_gather;
} }
static int aead_aes_gcm_init_randnonce(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len,
size_t requested_tag_len) {
if (requested_tag_len != EVP_AEAD_DEFAULT_TAG_LENGTH) {
if (requested_tag_len < AES_GCM_NONCE_LENGTH) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
requested_tag_len -= AES_GCM_NONCE_LENGTH;
}
if (!aead_aes_gcm_init(ctx, key, key_len, requested_tag_len)) {
return 0;
}
ctx->tag_len += AES_GCM_NONCE_LENGTH;
return 1;
}
static int aead_aes_gcm_seal_scatter_randnonce(
const EVP_AEAD_CTX *ctx,
uint8_t *out, uint8_t *out_tag, size_t *out_tag_len, size_t max_out_tag_len,
const uint8_t *external_nonce, size_t external_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) {
if (external_nonce_len != 0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
return 0;
}
uint8_t nonce[AES_GCM_NONCE_LENGTH];
if (max_out_tag_len < sizeof(nonce)) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
return 0;
}
RAND_bytes(nonce, sizeof(nonce));
const struct aead_aes_gcm_ctx *gcm_ctx =
(const struct aead_aes_gcm_ctx *)&ctx->state;
if (!aead_aes_gcm_seal_scatter_impl(gcm_ctx, out, out_tag, out_tag_len,
max_out_tag_len - AES_GCM_NONCE_LENGTH,
nonce, sizeof(nonce), in, in_len,
extra_in, extra_in_len, ad, ad_len,
ctx->tag_len - AES_GCM_NONCE_LENGTH)) {
return 0;
}
assert(*out_tag_len + sizeof(nonce) <= max_out_tag_len);
memcpy(out_tag + *out_tag_len, nonce, sizeof(nonce));
*out_tag_len += sizeof(nonce);
return 1;
}
static int aead_aes_gcm_open_gather_randnonce(
const EVP_AEAD_CTX *ctx, uint8_t *out,
const uint8_t *external_nonce, size_t external_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) {
if (external_nonce_len != 0) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
return 0;
}
if (in_tag_len < AES_GCM_NONCE_LENGTH) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
return 0;
}
const uint8_t *nonce = in_tag + in_tag_len - AES_GCM_NONCE_LENGTH;
const struct aead_aes_gcm_ctx *gcm_ctx =
(const struct aead_aes_gcm_ctx *)&ctx->state;
return aead_aes_gcm_open_gather_impl(
gcm_ctx, out, nonce, AES_GCM_NONCE_LENGTH, in, in_len, in_tag,
in_tag_len - AES_GCM_NONCE_LENGTH, ad, ad_len,
ctx->tag_len - AES_GCM_NONCE_LENGTH);
}
DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_128_gcm_randnonce) {
memset(out, 0, sizeof(EVP_AEAD));
out->key_len = 16;
out->nonce_len = 0;
out->overhead = EVP_AEAD_AES_GCM_TAG_LEN + AES_GCM_NONCE_LENGTH;
out->max_tag_len = EVP_AEAD_AES_GCM_TAG_LEN + AES_GCM_NONCE_LENGTH;
out->seal_scatter_supports_extra_in = 1;
out->init = aead_aes_gcm_init_randnonce;
out->cleanup = aead_aes_gcm_cleanup;
out->seal_scatter = aead_aes_gcm_seal_scatter_randnonce;
out->open_gather = aead_aes_gcm_open_gather_randnonce;
}
DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_256_gcm_randnonce) {
memset(out, 0, sizeof(EVP_AEAD));
out->key_len = 32;
out->nonce_len = 0;
out->overhead = EVP_AEAD_AES_GCM_TAG_LEN + AES_GCM_NONCE_LENGTH;
out->max_tag_len = EVP_AEAD_AES_GCM_TAG_LEN + AES_GCM_NONCE_LENGTH;
out->seal_scatter_supports_extra_in = 1;
out->init = aead_aes_gcm_init_randnonce;
out->cleanup = aead_aes_gcm_cleanup;
out->seal_scatter = aead_aes_gcm_seal_scatter_randnonce;
out->open_gather = aead_aes_gcm_open_gather_randnonce;
}
struct aead_aes_gcm_tls12_ctx { struct aead_aes_gcm_tls12_ctx {
struct aead_aes_gcm_ctx gcm_ctx; struct aead_aes_gcm_ctx gcm_ctx;
uint64_t min_next_nonce; uint64_t min_next_nonce;

@ -146,6 +146,30 @@ OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm_siv(void);
// https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02 // https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void); OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void);
// EVP_aead_aes_128_gcm_randnonce is AES-128 in Galois Counter Mode with
// internal nonce generation. The 12-byte nonce is appended to the tag
// and is generated internally. The "tag", for the purpurses of the API, is thus
// 12 bytes larger. The nonce parameter when using this AEAD must be
// zero-length. Since the nonce is random, a single key should not be used for
// more than 2^32 seal operations.
//
// Warning: this is for use for FIPS compliance only. It is probably not
// suitable for other uses. Using standard AES-GCM AEADs allows one to achieve
// the same effect, but gives more control over nonce storage.
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm_randnonce(void);
// EVP_aead_aes_256_gcm_randnonce is AES-256 in Galois Counter Mode with
// internal nonce generation. The 12-byte nonce is appended to the tag
// and is generated internally. The "tag", for the purpurses of the API, is thus
// 12 bytes larger. The nonce parameter when using this AEAD must be
// zero-length. Since the nonce is random, a single key should not be used for
// more than 2^32 seal operations.
//
// Warning: this is for use for FIPS compliance only. It is probably not
// suitable for other uses. Using standard AES-GCM AEADs allows one to achieve
// the same effect, but gives more control over nonce storage.
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm_randnonce(void);
// EVP_aead_aes_128_ccm_bluetooth is AES-128-CCM with M=4 and L=2 (4-byte tags // EVP_aead_aes_128_ccm_bluetooth is AES-128-CCM with M=4 and L=2 (4-byte tags
// and 13-byte nonces), as decribed in the Bluetooth Core Specification v5.0, // and 13-byte nonces), as decribed in the Bluetooth Core Specification v5.0,
// Volume 6, Part E, Section 1. // Volume 6, Part E, Section 1.

@ -12,6 +12,7 @@ set(
crypto/cipher_extra/test/aes_128_ccm_bluetooth_tests.txt crypto/cipher_extra/test/aes_128_ccm_bluetooth_tests.txt
crypto/cipher_extra/test/aes_128_ccm_bluetooth_8_tests.txt crypto/cipher_extra/test/aes_128_ccm_bluetooth_8_tests.txt
crypto/cipher_extra/test/aes_128_ctr_hmac_sha256.txt crypto/cipher_extra/test/aes_128_ctr_hmac_sha256.txt
crypto/cipher_extra/test/aes_128_gcm_randnonce_tests.txt
crypto/cipher_extra/test/aes_128_gcm_siv_tests.txt crypto/cipher_extra/test/aes_128_gcm_siv_tests.txt
crypto/cipher_extra/test/aes_128_gcm_tests.txt crypto/cipher_extra/test/aes_128_gcm_tests.txt
crypto/cipher_extra/test/aes_192_gcm_tests.txt crypto/cipher_extra/test/aes_192_gcm_tests.txt
@ -20,6 +21,7 @@ set(
crypto/cipher_extra/test/aes_256_cbc_sha256_tls_tests.txt crypto/cipher_extra/test/aes_256_cbc_sha256_tls_tests.txt
crypto/cipher_extra/test/aes_256_cbc_sha384_tls_tests.txt crypto/cipher_extra/test/aes_256_cbc_sha384_tls_tests.txt
crypto/cipher_extra/test/aes_256_ctr_hmac_sha256.txt crypto/cipher_extra/test/aes_256_ctr_hmac_sha256.txt
crypto/cipher_extra/test/aes_256_gcm_randnonce_tests.txt
crypto/cipher_extra/test/aes_256_gcm_siv_tests.txt crypto/cipher_extra/test/aes_256_gcm_siv_tests.txt
crypto/cipher_extra/test/aes_256_gcm_tests.txt crypto/cipher_extra/test/aes_256_gcm_tests.txt
crypto/cipher_extra/test/chacha20_poly1305_tests.txt crypto/cipher_extra/test/chacha20_poly1305_tests.txt

Loading…
Cancel
Save