Skip to content

Commit

Permalink
Migrate OCB3 to Rust (#9569)
Browse files Browse the repository at this point in the history
  • Loading branch information
alex authored Sep 14, 2023
1 parent d167a2e commit 51ea13e
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 97 deletions.
6 changes: 1 addition & 5 deletions src/cryptography/hazmat/backends/openssl/aead.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@
from cryptography.hazmat.primitives.ciphers.aead import (
AESCCM,
AESGCM,
AESOCB3,
ChaCha20Poly1305,
)

_AEADTypes = typing.Union[AESCCM, AESGCM, AESOCB3, ChaCha20Poly1305]
_AEADTypes = typing.Union[AESCCM, AESGCM, ChaCha20Poly1305]


def _is_evp_aead_supported_cipher(
Expand Down Expand Up @@ -220,16 +219,13 @@ def _evp_cipher_cipher_name(cipher: _AEADTypes) -> bytes:
from cryptography.hazmat.primitives.ciphers.aead import (
AESCCM,
AESGCM,
AESOCB3,
ChaCha20Poly1305,
)

if isinstance(cipher, ChaCha20Poly1305):
return b"chacha20-poly1305"
elif isinstance(cipher, AESCCM):
return f"aes-{len(cipher._key) * 8}-ccm".encode("ascii")
elif isinstance(cipher, AESOCB3):
return f"aes-{len(cipher._key) * 8}-ocb".encode("ascii")
else:
assert isinstance(cipher, AESGCM)
return f"aes-{len(cipher._key) * 8}-gcm".encode("ascii")
Expand Down
17 changes: 17 additions & 0 deletions src/cryptography/hazmat/bindings/_rust/openssl/aead.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,20 @@ class AESSIV:
data: bytes,
associated_data: list[bytes] | None,
) -> bytes: ...

class AESOCB3:
def __init__(self, key: bytes) -> None: ...
@staticmethod
def generate_key(key_size: int) -> bytes: ...
def encrypt(
self,
nonce: bytes,
data: bytes,
associated_data: bytes | None,
) -> bytes: ...
def decrypt(
self,
nonce: bytes,
data: bytes,
associated_data: bytes | None,
) -> bytes: ...
70 changes: 1 addition & 69 deletions src/cryptography/hazmat/primitives/ciphers/aead.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
]

AESSIV = rust_openssl.aead.AESSIV
AESOCB3 = rust_openssl.aead.AESOCB3


class ChaCha20Poly1305:
Expand Down Expand Up @@ -242,72 +243,3 @@ def _check_params(
utils._check_byteslike("associated_data", associated_data)
if len(nonce) < 8 or len(nonce) > 128:
raise ValueError("Nonce must be between 8 and 128 bytes")


class AESOCB3:
_MAX_SIZE = 2**31 - 1

def __init__(self, key: bytes):
utils._check_byteslike("key", key)
if len(key) not in (16, 24, 32):
raise ValueError("AESOCB3 key must be 128, 192, or 256 bits.")

self._key = key

if not backend.aead_cipher_supported(self):
raise exceptions.UnsupportedAlgorithm(
"OCB3 is not supported by this version of OpenSSL",
exceptions._Reasons.UNSUPPORTED_CIPHER,
)

@classmethod
def generate_key(cls, bit_length: int) -> bytes:
if not isinstance(bit_length, int):
raise TypeError("bit_length must be an integer")

if bit_length not in (128, 192, 256):
raise ValueError("bit_length must be 128, 192, or 256")

return os.urandom(bit_length // 8)

def encrypt(
self,
nonce: bytes,
data: bytes,
associated_data: bytes | None,
) -> bytes:
if associated_data is None:
associated_data = b""

if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE:
# This is OverflowError to match what cffi would raise
raise OverflowError(
"Data or associated data too long. Max 2**31 - 1 bytes"
)

self._check_params(nonce, data, associated_data)
return aead._encrypt(backend, self, nonce, data, [associated_data], 16)

def decrypt(
self,
nonce: bytes,
data: bytes,
associated_data: bytes | None,
) -> bytes:
if associated_data is None:
associated_data = b""

self._check_params(nonce, data, associated_data)
return aead._decrypt(backend, self, nonce, data, [associated_data], 16)

def _check_params(
self,
nonce: bytes,
data: bytes,
associated_data: bytes,
) -> None:
utils._check_byteslike("nonce", nonce)
utils._check_byteslike("data", data)
utils._check_byteslike("associated_data", associated_data)
if len(nonce) < 12 or len(nonce) > 15:
raise ValueError("Nonce must be between 12 and 15 bytes")
1 change: 1 addition & 0 deletions src/rust/Cargo.lock

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

1 change: 1 addition & 0 deletions src/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ rust-version = "1.63.0"

[dependencies]
once_cell = "1"
cfg-if = "1"
pyo3 = { version = "0.19", features = ["abi3-py37"] }
asn1 = { version = "0.15.5", default-features = false }
cryptography-cffi = { path = "cryptography-cffi" }
Expand Down
Loading

0 comments on commit 51ea13e

Please sign in to comment.