Skip to content

Commit

Permalink
Add support for AES-GCM-SIV using OpenSSL>=3.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
facutuesca committed Nov 27, 2023
1 parent 7387983 commit 8e83704
Show file tree
Hide file tree
Showing 15 changed files with 1,700 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ Changelog
* In the next release (43.0.0) of cryptography, loading an X.509 certificate
with a negative serial number will raise an exception. This has been
deprecated since 36.0.0.
* Added support for
:class:`~cryptography.hazmat.primitives.ciphers.aead.AESGCMSIV` when using
OpenSSL 3.2.0+.

.. _v41-0-5:

Expand Down
28 changes: 28 additions & 0 deletions docs/development/custom-vectors/aes-192-gcm-siv.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
AES-GCM-SIV vector creation
===========================

This page documents the code that was used to generate the AES-GCM-SIV test
vectors for key lengths not available in the OpenSSL test vectors. All the
vectors were generated using OpenSSL and verified with Rust.

Creation
--------

The following Python script was run to generate the vector files. The OpenSSL
test vectors were used as a base and modified to have 192-bit key length.

.. literalinclude:: /development/custom-vectors/aes-192-gcm-siv/generate_aes192gcmsiv.py

Download link: :download:`generate_aes192gcmsiv.py
</development/custom-vectors/aes-192-gcm-siv/generate_aes192gcmsiv.py>`


Verification
------------

The following Rust program was used to verify the vectors.

.. literalinclude:: /development/custom-vectors/aes-192-gcm-siv/verify-aes192gcmsiv/src/main.rs

Download link: :download:`main.rs
</development/custom-vectors/aes-192-gcm-siv/verify-aes192gcmsiv/src/main.rs>`
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.

import binascii

from cryptography.hazmat.primitives.ciphers.aead import AESGCMSIV


def convert_key_to_192_bits(key: str) -> str:
"""
This takes existing 128 and 256-bit keys from test vectors from OpenSSL
and makes them 192-bit by either appending 0 or truncating the key.
"""
new_key = binascii.unhexlify(key)
if len(new_key) == 16:
new_key += b"\x00" * 8
elif len(new_key) == 32:
new_key = new_key[0:24]
else:
raise RuntimeError(
"Unexpected key length. OpenSSL AES-GCM-SIV test vectors only "
"contain 128-bit and 256-bit keys"
)

return binascii.hexlify(new_key).decode("ascii")


def encrypt(key: str, iv: str, plaintext: str, aad: str) -> (str, str):
aesgcmsiv = AESGCMSIV(binascii.unhexlify(key))
encrypted_output = aesgcmsiv.encrypt(
binascii.unhexlify(iv),
binascii.unhexlify(plaintext),
binascii.unhexlify(aad) if aad else None,
)
ciphertext, tag = encrypted_output[:-16], encrypted_output[-16:]

return (
binascii.hexlify(ciphertext).decode("ascii"),
binascii.hexlify(tag).decode("ascii"),
)


def build_vectors(filename):
count = 0
output = []
key = None
iv = None
aad = None
plaintext = None

with open(filename) as vector_file:
for line in vector_file:
line = line.strip()
if line.startswith("Key"):
if count != 0:
ciphertext, tag = encrypt(key, iv, plaintext, aad)
output.append(f"Tag = {tag}\nCiphertext = {ciphertext}\n")
output.append(f"\nCOUNT = {count}")
count += 1
aad = None
_, key = line.split(" = ")
key = convert_key_to_192_bits(key)
output.append(f"Key = {key}")
elif line.startswith("IV"):
_, iv = line.split(" = ")
output.append(f"IV = {iv}")
elif line.startswith("AAD"):
_, aad = line.split(" = ")
output.append(f"AAD = {aad}")
elif line.startswith("Plaintext"):
_, plaintext = line.split(" = ")
output.append(f"Plaintext = {plaintext}")

ciphertext, tag = encrypt(key, iv, plaintext, aad)
output.append(f"Tag = {tag}\nCiphertext = {ciphertext}\n")
return "\n".join(output)


def write_file(data, filename):
with open(filename, "w") as f:
f.write(data)


path = "vectors/cryptography_vectors/ciphers/AES/GCM-SIV/openssl.txt"
write_file(build_vectors(path), "aes-192-gcm-siv.txt")

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "verify-aes192gcmsiv"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
aes-gcm-siv = "0.11.1"
aes = "0.8.1"
hex = "0.4.3"
Loading

0 comments on commit 8e83704

Please sign in to comment.