aws_lc_rs/kdf/
kbkdf.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0 OR ISC
3
4#![allow(clippy::module_name_repetitions)]
5
6use crate::aws_lc::{KBKDF_ctr_hmac, EVP_MD};
7
8use crate::digest::{match_digest_type, AlgorithmID};
9use crate::error::Unspecified;
10use crate::ptr::ConstPointer;
11
12/// KBKDF in Counter Mode with HMAC-SHA224
13#[allow(dead_code)]
14const KBKDF_CTR_HMAC_SHA224: KbkdfCtrHmacAlgorithm = KbkdfCtrHmacAlgorithm {
15    id: KbkdfCtrHmacAlgorithmId::Sha224,
16};
17
18/// KBKDF in Counter Mode with HMAC-SHA256
19#[allow(dead_code)]
20const KBKDF_CTR_HMAC_SHA256: KbkdfCtrHmacAlgorithm = KbkdfCtrHmacAlgorithm {
21    id: KbkdfCtrHmacAlgorithmId::Sha256,
22};
23
24/// KBKDF in Counter Mode with HMAC-SHA384
25#[allow(dead_code)]
26const KBKDF_CTR_HMAC_SHA384: KbkdfCtrHmacAlgorithm = KbkdfCtrHmacAlgorithm {
27    id: KbkdfCtrHmacAlgorithmId::Sha384,
28};
29
30/// KBKDF in Counter Mode with HMAC-SHA512
31#[allow(dead_code)]
32const KBKDF_CTR_HMAC_SHA512: KbkdfCtrHmacAlgorithm = KbkdfCtrHmacAlgorithm {
33    id: KbkdfCtrHmacAlgorithmId::Sha512,
34};
35
36/// Retrieve [`KbkdfCtrHmacAlgorithm`] using the [`KbkdfCtrHmacAlgorithmId`] specified by `id`.
37#[must_use]
38pub const fn get_kbkdf_ctr_hmac_algorithm(
39    id: KbkdfCtrHmacAlgorithmId,
40) -> Option<&'static KbkdfCtrHmacAlgorithm> {
41    {
42        Some(match id {
43            KbkdfCtrHmacAlgorithmId::Sha224 => &KBKDF_CTR_HMAC_SHA224,
44            KbkdfCtrHmacAlgorithmId::Sha256 => &KBKDF_CTR_HMAC_SHA256,
45            KbkdfCtrHmacAlgorithmId::Sha384 => &KBKDF_CTR_HMAC_SHA384,
46            KbkdfCtrHmacAlgorithmId::Sha512 => &KBKDF_CTR_HMAC_SHA512,
47        })
48    }
49}
50
51/// KBKDF in Counter Mode with HMAC Algorithm
52pub struct KbkdfCtrHmacAlgorithm {
53    id: KbkdfCtrHmacAlgorithmId,
54}
55
56impl KbkdfCtrHmacAlgorithm {
57    /// Returns the KBKDF Counter HMAC Algorithm Identifier
58    #[must_use]
59    pub fn id(&self) -> KbkdfCtrHmacAlgorithmId {
60        self.id
61    }
62
63    #[must_use]
64    fn get_evp_md(&self) -> ConstPointer<EVP_MD> {
65        match_digest_type(match self.id {
66            KbkdfCtrHmacAlgorithmId::Sha224 => &AlgorithmID::SHA224,
67            KbkdfCtrHmacAlgorithmId::Sha256 => &AlgorithmID::SHA256,
68            KbkdfCtrHmacAlgorithmId::Sha384 => &AlgorithmID::SHA384,
69            KbkdfCtrHmacAlgorithmId::Sha512 => &AlgorithmID::SHA512,
70        })
71    }
72}
73
74impl PartialEq for KbkdfCtrHmacAlgorithm {
75    fn eq(&self, other: &Self) -> bool {
76        self.id == other.id
77    }
78}
79
80impl Eq for KbkdfCtrHmacAlgorithm {}
81
82impl core::fmt::Debug for KbkdfCtrHmacAlgorithm {
83    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
84        core::fmt::Debug::fmt(&self.id, f)
85    }
86}
87
88/// Key-based Derivation Function Algorithm Identifier
89#[non_exhaustive]
90#[derive(Clone, Copy, PartialEq, Eq, Debug)]
91pub enum KbkdfCtrHmacAlgorithmId {
92    /// KBKDF in Counter Mode with HMAC-SHA224
93    Sha224,
94
95    /// KBKDF in Counter Mode with HMAC-SHA256
96    Sha256,
97
98    /// KBKDF in Counter Mode with HMAC-SHA384
99    Sha384,
100
101    /// KBKDF in Counter Mode with HMAC-SHA512
102    Sha512,
103}
104
105/// # Key-based Key Derivation Function (KBKDF) in Counter Mode with HMAC PRF
106///
107/// ## Input Validation and Defaults
108/// * `output.len() > 0 and `secret.len() > 0`
109/// * `output.len() <= usize::MAX - DIGEST_LENGTH`
110/// * The requested `output.len()` would result in overflowing the counter.
111///
112/// ## Implementation Notes
113///
114/// This implementation adheres to the algorithm specified in Section 4.1 of the
115/// NIST Special Publication 800-108 Revision 1 Update 1 published on August
116/// 2022. Using HMAC as the PRF function. In this implementation:
117/// * The counter is 32-bits and is represented in big-endian format
118/// * The counter is placed before the fixed info string
119///
120/// Specification available at <https://doi.org/10.6028/NIST.SP.800-108r1-upd1>
121///
122/// # Errors
123/// `Unspecified` is returned if input validation fails or an unexpected error occurs.
124pub fn kbkdf_ctr_hmac(
125    algorithm: &'static KbkdfCtrHmacAlgorithm,
126    secret: &[u8],
127    info: &[u8],
128    output: &mut [u8],
129) -> Result<(), Unspecified> {
130    let evp_md = algorithm.get_evp_md();
131    let out_len = output.len();
132    if 1 != unsafe {
133        KBKDF_ctr_hmac(
134            output.as_mut_ptr(),
135            out_len,
136            *evp_md,
137            secret.as_ptr(),
138            secret.len(),
139            info.as_ptr(),
140            info.len(),
141        )
142    } {
143        return Err(Unspecified);
144    }
145    Ok(())
146}