Skip to main content

reallyme_crypto/
dispatch.rs

1// SPDX-FileCopyrightText: Copyright © 2026 ReallyMe LLC. All rights reserved
2//
3// SPDX-License-Identifier: Apache-2.0
4
5//! Root dispatch facade.
6
7use crypto_core::{
8    AeadAlgorithm, CryptoError, HashAlgorithm, MacAlgorithm, MacFailureKind, MacHash,
9};
10use zeroize::Zeroizing;
11
12pub use crypto_dispatch::{
13    derive_keypair, derive_shared_secret, generate_keypair, generate_multikey_keypair,
14    kem_decapsulate, kem_encapsulate, provider_decision, public_key_to_multikey, sign,
15    validate_verification_method_multikey, verify, AlgorithmError, FallbackPolicy,
16    GeneratedKeypair, KeyCopyBoundary, KeyResidency, ProviderDecision, ProviderDisposition,
17    ProviderKind, ProviderLane, ProviderOperation, ProviderOutputPolicy, ProviderPolicyReason,
18};
19
20/// Borrowed AEAD inputs for the root operation-backed dispatch facade.
21///
22/// Key and nonce lengths are validated by the semantic operation owner. The
23/// adapter borrows caller buffers and never truncates, pads, or retains them.
24pub struct AeadParams<'a> {
25    /// Symmetric key bytes borrowed for one AEAD operation.
26    pub key: &'a [u8],
27    /// Nonce bytes borrowed for one AEAD operation.
28    pub nonce: &'a [u8],
29    /// Additional authenticated data bound to the ciphertext.
30    pub aad: &'a [u8],
31}
32
33/// Borrowed MAC inputs for the root operation-backed dispatch facade.
34///
35/// The operation owner validates the key before authentication or verification;
36/// this adapter never truncates, pads, or retains caller-owned key material.
37pub struct MacParams<'a> {
38    /// Symmetric key bytes borrowed for the duration of one MAC operation.
39    pub key: &'a [u8],
40}
41
42/// Compute a digest through the operation-layer semantic owner.
43pub fn hash_digest(algorithm: HashAlgorithm, message: &[u8]) -> Result<Vec<u8>, AlgorithmError> {
44    crate::operations::hash::digest(algorithm, message).map_err(|error| match error {
45        crate::operations::OperationError::Provider {
46            reason: crate::operations::ProviderErrorReason::UnsupportedAlgorithm,
47        } => AlgorithmError::UnsupportedHashAlgorithm(algorithm),
48        _ => AlgorithmError::Crypto(CryptoError::Unsupported),
49    })
50}
51
52/// Encrypts with an AEAD through the operation-layer semantic owner.
53pub fn aead_encrypt(
54    algorithm: AeadAlgorithm,
55    params: &AeadParams<'_>,
56    plaintext: &[u8],
57) -> Result<Vec<u8>, AlgorithmError> {
58    crate::operations::aead::seal(algorithm, params.key, params.nonce, params.aad, plaintext)
59        .map_err(|error| {
60            aead_algorithm_error_from_operation_error(
61                algorithm,
62                crate::aead_error::AeadOperation::Seal,
63                error,
64                params.key.len(),
65                params.nonce.len(),
66                plaintext.len(),
67            )
68        })
69}
70
71/// Decrypts with an AEAD through the operation-layer semantic owner.
72pub fn aead_decrypt(
73    algorithm: AeadAlgorithm,
74    params: &AeadParams<'_>,
75    ciphertext_with_tag: &[u8],
76) -> Result<Zeroizing<Vec<u8>>, AlgorithmError> {
77    crate::operations::aead::open(
78        algorithm,
79        params.key,
80        params.nonce,
81        params.aad,
82        ciphertext_with_tag,
83    )
84    .map_err(|error| {
85        aead_algorithm_error_from_operation_error(
86            algorithm,
87            crate::aead_error::AeadOperation::Open,
88            error,
89            params.key.len(),
90            params.nonce.len(),
91            ciphertext_with_tag.len(),
92        )
93    })
94}
95
96fn aead_algorithm_error_from_operation_error(
97    algorithm: AeadAlgorithm,
98    operation: crate::aead_error::AeadOperation,
99    error: crate::operations::OperationError,
100    key_len: usize,
101    nonce_len: usize,
102    input_len: usize,
103) -> AlgorithmError {
104    match error {
105        crate::operations::OperationError::Provider {
106            reason: crate::operations::ProviderErrorReason::UnsupportedAlgorithm,
107        } => AlgorithmError::UnsupportedAeadAlgorithm(algorithm),
108        _ => AlgorithmError::Crypto(crate::aead_error::crypto_error_from_operation_error(
109            algorithm, operation, error, key_len, nonce_len, input_len,
110        )),
111    }
112}
113
114/// Computes a MAC tag through the operation-layer semantic owner.
115pub fn mac_authenticate(
116    algorithm: MacAlgorithm,
117    params: &MacParams<'_>,
118    message: &[u8],
119) -> Result<Vec<u8>, AlgorithmError> {
120    crate::operations::mac::authenticate(algorithm, params.key, message)
121        .map_err(|error| mac_algorithm_error_from_operation_error(algorithm, error))
122}
123
124/// Verifies a MAC tag through the operation-layer semantic owner.
125pub fn mac_verify(
126    algorithm: MacAlgorithm,
127    params: &MacParams<'_>,
128    message: &[u8],
129    tag: &[u8],
130) -> Result<(), AlgorithmError> {
131    crate::operations::mac::verify(algorithm, params.key, message, tag)
132        .map_err(|error| mac_algorithm_error_from_operation_error(algorithm, error))
133}
134
135fn mac_algorithm_error_from_operation_error(
136    algorithm: MacAlgorithm,
137    error: crate::operations::OperationError,
138) -> AlgorithmError {
139    let kind = match error {
140        crate::operations::OperationError::Primitive {
141            reason: crate::operations::PrimitiveErrorReason::InvalidKey,
142        } => MacFailureKind::InvalidKeyLength,
143        crate::operations::OperationError::Primitive {
144            reason: crate::operations::PrimitiveErrorReason::InvalidLength,
145        } => MacFailureKind::InvalidTagLength,
146        crate::operations::OperationError::Primitive {
147            reason: crate::operations::PrimitiveErrorReason::VerificationFailed,
148        } => MacFailureKind::VerificationFailed,
149        crate::operations::OperationError::Provider {
150            reason: crate::operations::ProviderErrorReason::UnsupportedAlgorithm,
151        } => return AlgorithmError::UnsupportedMacAlgorithm(algorithm),
152        _ => MacFailureKind::BackendFailure,
153    };
154
155    AlgorithmError::Crypto(CryptoError::Mac {
156        hash: mac_hash(algorithm),
157        kind,
158    })
159}
160
161fn mac_hash(algorithm: MacAlgorithm) -> MacHash {
162    match algorithm {
163        MacAlgorithm::HmacSha256 => MacHash::Sha2_256,
164        MacAlgorithm::HmacSha384 => MacHash::Sha2_384,
165        MacAlgorithm::HmacSha512 => MacHash::Sha2_512,
166    }
167}