Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert CMAC to Rust #9639

Merged
merged 1 commit into from
Nov 1, 2023
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
5 changes: 0 additions & 5 deletions src/cryptography/hazmat/backends/openssl/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
from cryptography.hazmat.backends.openssl import aead
from cryptography.hazmat.backends.openssl.ciphers import _CipherContext
from cryptography.hazmat.backends.openssl.cmac import _CMACContext
from cryptography.hazmat.bindings._rust import openssl as rust_openssl
from cryptography.hazmat.bindings.openssl import binding
from cryptography.hazmat.primitives import hashes, serialization
Expand All @@ -31,7 +30,6 @@
PublicKeyTypes,
)
from cryptography.hazmat.primitives.ciphers import (
BlockCipherAlgorithm,
CipherAlgorithm,
)
from cryptography.hazmat.primitives.ciphers.algorithms import (
Expand Down Expand Up @@ -571,9 +569,6 @@ def cmac_algorithm_supported(self, algorithm) -> bool:
algorithm, CBC(b"\x00" * algorithm.block_size)
)

def create_cmac_ctx(self, algorithm: BlockCipherAlgorithm) -> _CMACContext:
return _CMACContext(self, algorithm)

def load_pem_private_key(
self,
data: bytes,
Expand Down
89 changes: 0 additions & 89 deletions src/cryptography/hazmat/backends/openssl/cmac.py

This file was deleted.

2 changes: 2 additions & 0 deletions src/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import typing

from cryptography.hazmat.bindings._rust.openssl import (
aead,
cmac,
dh,
dsa,
ec,
Expand All @@ -24,6 +25,7 @@ __all__ = [
"openssl_version",
"raise_openssl_error",
"aead",
"cmac",
"dh",
"dsa",
"ec",
Expand Down
18 changes: 18 additions & 0 deletions src/cryptography/hazmat/bindings/_rust/openssl/cmac.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# 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 typing

from cryptography.hazmat.primitives import ciphers

class CMAC:
def __init__(
self,
algorithm: ciphers.BlockCipherAlgorithm,
backend: typing.Any = None,
) -> None: ...
def update(self, data: bytes) -> None: ...
def finalize(self) -> bytes: ...
def verify(self, signature: bytes) -> None: ...
def copy(self) -> CMAC: ...
61 changes: 3 additions & 58 deletions src/cryptography/hazmat/primitives/cmac.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,62 +4,7 @@

from __future__ import annotations

import typing
from cryptography.hazmat.bindings._rust import openssl as rust_openssl

from cryptography import utils
from cryptography.exceptions import AlreadyFinalized
from cryptography.hazmat.primitives import ciphers

if typing.TYPE_CHECKING:
from cryptography.hazmat.backends.openssl.cmac import _CMACContext


class CMAC:
_ctx: _CMACContext | None
_algorithm: ciphers.BlockCipherAlgorithm

def __init__(
self,
algorithm: ciphers.BlockCipherAlgorithm,
backend: typing.Any = None,
ctx: _CMACContext | None = None,
) -> None:
if not isinstance(algorithm, ciphers.BlockCipherAlgorithm):
raise TypeError("Expected instance of BlockCipherAlgorithm.")
self._algorithm = algorithm

if ctx is None:
from cryptography.hazmat.backends.openssl.backend import (
backend as ossl,
)

self._ctx = ossl.create_cmac_ctx(self._algorithm)
else:
self._ctx = ctx

def update(self, data: bytes) -> None:
if self._ctx is None:
raise AlreadyFinalized("Context was already finalized.")

utils._check_bytes("data", data)
self._ctx.update(data)

def finalize(self) -> bytes:
if self._ctx is None:
raise AlreadyFinalized("Context was already finalized.")
digest = self._ctx.finalize()
self._ctx = None
return digest

def verify(self, signature: bytes) -> None:
utils._check_bytes("signature", signature)
if self._ctx is None:
raise AlreadyFinalized("Context was already finalized.")

ctx, self._ctx = self._ctx, None
ctx.verify(signature)

def copy(self) -> CMAC:
if self._ctx is None:
raise AlreadyFinalized("Context was already finalized.")
return CMAC(self._algorithm, ctx=self._ctx.copy())
__all__ = ["CMAC"]
CMAC = rust_openssl.cmac.CMAC
6 changes: 6 additions & 0 deletions src/rust/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,10 @@ fn main() {
if env::var("DEP_OPENSSL_BORINGSSL").is_ok() {
println!("cargo:rustc-cfg=CRYPTOGRAPHY_IS_BORINGSSL");
}

if let Ok(vars) = env::var("DEP_OPENSSL_CONF") {
for var in vars.split(',') {
println!("cargo:rustc-cfg=CRYPTOGRAPHY_OSSLCONF=\"{}\"", var);
}
}
}
71 changes: 71 additions & 0 deletions src/rust/cryptography-openssl/src/cmac.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// 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.

use crate::hmac::DigestBytes;
use crate::{cvt, cvt_p, OpenSSLResult};
use foreign_types_shared::{ForeignType, ForeignTypeRef};
use std::ptr;

foreign_types::foreign_type! {
type CType = ffi::CMAC_CTX;
fn drop = ffi::CMAC_CTX_free;

pub struct Cmac;
pub struct CmacRef;
}

// SAFETY: It's safe to have `&` references from multiple threads.
unsafe impl Sync for Cmac {}
// SAFETY: It's safe to move the `Cmac` from one thread to another.
unsafe impl Send for Cmac {}

impl Cmac {
pub fn new(key: &[u8], cipher: &openssl::symm::Cipher) -> OpenSSLResult<Cmac> {
// SAFETY: All FFI conditions are handled.
unsafe {
let ctx = Cmac::from_ptr(cvt_p(ffi::CMAC_CTX_new())?);
cvt(ffi::CMAC_Init(
ctx.as_ptr(),
key.as_ptr().cast(),
key.len(),
cipher.as_ptr(),
ptr::null_mut(),
))?;
Ok(ctx)
}
}
}

impl CmacRef {
pub fn update(&mut self, data: &[u8]) -> OpenSSLResult<()> {
// SAFETY: All FFI conditions are handled.
unsafe {
cvt(ffi::CMAC_Update(
self.as_ptr(),
data.as_ptr().cast(),
data.len(),
))?;
}
Ok(())
}

pub fn finish(&mut self) -> OpenSSLResult<DigestBytes> {
let mut buf = [0; ffi::EVP_MAX_MD_SIZE as usize];
let mut len = ffi::EVP_MAX_MD_SIZE as usize;
// SAFETY: All FFI conditions are handled.
unsafe {
cvt(ffi::CMAC_Final(self.as_ptr(), buf.as_mut_ptr(), &mut len))?;
}
Ok(DigestBytes { buf, len })
}

pub fn copy(&self) -> OpenSSLResult<Cmac> {
// SAFETY: All FFI conditions are handled.
unsafe {
let h = Cmac::from_ptr(cvt_p(ffi::CMAC_CTX_new())?);
cvt(ffi::CMAC_CTX_copy(h.as_ptr(), self.as_ptr()))?;
Ok(h)
}
}
}
4 changes: 2 additions & 2 deletions src/rust/cryptography-openssl/src/hmac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ impl HmacRef {
}

pub struct DigestBytes {
buf: [u8; ffi::EVP_MAX_MD_SIZE as usize],
len: usize,
pub(crate) buf: [u8; ffi::EVP_MAX_MD_SIZE as usize],
pub(crate) len: usize,
}

impl std::ops::Deref for DigestBytes {
Expand Down
1 change: 1 addition & 0 deletions src/rust/cryptography-openssl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#![deny(rust_2018_idioms, clippy::undocumented_unsafe_blocks)]

pub mod cmac;
pub mod fips;
pub mod hmac;
#[cfg(any(CRYPTOGRAPHY_IS_BORINGSSL, CRYPTOGRAPHY_IS_LIBRESSL))]
Expand Down
Loading
Loading