Skip to main content

crypto_core/error/
kdf.rs

1// SPDX-FileCopyrightText: Copyright © 2026 ReallyMe LLC. All rights reserved
2//
3// SPDX-License-Identifier: Apache-2.0
4
5/// Password-based key derivation algorithm identifier.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7#[non_exhaustive]
8pub enum KdfAlgorithm {
9    /// Argon2id memory-hard KDF.
10    Argon2id,
11    /// PBKDF2 password-based KDF conforming to RFC 8018.
12    Pbkdf2,
13    /// NIST Concat KDF as profiled by JOSE/JWA ECDH-ES.
14    ConcatKdf,
15    /// KMAC256 from NIST SP 800-185.
16    Kmac256,
17}
18
19impl core::fmt::Display for KdfAlgorithm {
20    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
21        let detail = match self {
22            KdfAlgorithm::Argon2id => "Argon2id",
23            KdfAlgorithm::Pbkdf2 => "PBKDF2",
24            KdfAlgorithm::ConcatKdf => "Concat KDF",
25            KdfAlgorithm::Kmac256 => "KMAC256",
26        };
27        write!(f, "{detail}")
28    }
29}
30
31/// Versioned parameter profile for the KDF.
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33#[non_exhaustive]
34pub enum KdfProfile {
35    /// Argon2id parameter profile version 1.
36    Argon2idV1,
37    /// Argon2id parameter profile version 2.
38    Argon2idV2,
39    /// PBKDF2 using HMAC-SHA-256 as the PRF.
40    Pbkdf2HmacSha256,
41    /// PBKDF2 using HMAC-SHA-512 as the PRF.
42    Pbkdf2HmacSha512,
43    /// JWA ECDH-ES Concat KDF using SHA-256.
44    JwaEcdhEsSha256,
45    /// NIST SP 800-185 KMAC256 with caller-supplied input and customization.
46    Sp800185Kmac256,
47}
48
49impl core::fmt::Display for KdfProfile {
50    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
51        let detail = match self {
52            KdfProfile::Argon2idV1 => "Argon2id v1",
53            KdfProfile::Argon2idV2 => "Argon2id v2",
54            KdfProfile::Pbkdf2HmacSha256 => "PBKDF2-HMAC-SHA-256",
55            KdfProfile::Pbkdf2HmacSha512 => "PBKDF2-HMAC-SHA-512",
56            KdfProfile::JwaEcdhEsSha256 => "JWA ECDH-ES Concat KDF SHA-256",
57            KdfProfile::Sp800185Kmac256 => "SP 800-185 KMAC256",
58        };
59        write!(f, "{detail}")
60    }
61}
62
63/// Specific reason a KDF operation failed.
64#[derive(Debug, Clone, Copy, PartialEq, Eq)]
65#[non_exhaustive]
66pub enum KdfFailureKind {
67    /// The secret/password input had an unacceptable length.
68    InvalidSecretLength,
69    /// The salt input had an unacceptable length.
70    InvalidSaltLength,
71    /// The requested output length was unacceptable.
72    InvalidOutputLength,
73    /// The iteration count was zero or outside this API's accepted range.
74    InvalidIterationCount,
75    /// The supplied KDF parameters were invalid.
76    InvalidParams,
77    /// The derivation itself did not succeed.
78    DerivationFailed,
79}
80
81impl core::fmt::Display for KdfFailureKind {
82    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
83        let detail = match self {
84            KdfFailureKind::InvalidSecretLength => "invalid secret length",
85            KdfFailureKind::InvalidSaltLength => "invalid salt length",
86            KdfFailureKind::InvalidOutputLength => "invalid output length",
87            KdfFailureKind::InvalidIterationCount => "invalid iteration count",
88            KdfFailureKind::InvalidParams => "invalid parameters",
89            KdfFailureKind::DerivationFailed => "derivation failed",
90        };
91        write!(f, "{detail}")
92    }
93}
94
95/// Hash function underlying an HKDF operation.
96#[derive(Debug, Clone, Copy, PartialEq, Eq)]
97#[non_exhaustive]
98pub enum HkdfHash {
99    /// HKDF using SHA-2-256.
100    Sha2_256,
101    /// HKDF using SHA-2-384.
102    Sha2_384,
103    /// HKDF using SHA-3-256.
104    Sha3_256,
105}
106
107impl core::fmt::Display for HkdfHash {
108    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
109        let detail = match self {
110            HkdfHash::Sha2_256 => "SHA2-256",
111            HkdfHash::Sha2_384 => "SHA2-384",
112            HkdfHash::Sha3_256 => "SHA3-256",
113        };
114        write!(f, "{detail}")
115    }
116}
117
118/// Specific reason an HKDF operation failed.
119#[derive(Debug, Clone, Copy, PartialEq, Eq)]
120#[non_exhaustive]
121pub enum HkdfFailureKind {
122    /// The input key material had an unacceptable length.
123    InvalidIkmLength,
124    /// The domain-separation tag had an unacceptable length.
125    InvalidDomainTagLength,
126    /// The domain-separation tag contained an invalid byte.
127    InvalidDomainTagByte,
128    /// An input length exceeded the representable range.
129    LengthOverflow,
130    /// The requested output length was unacceptable.
131    InvalidOutputLength,
132    /// The HKDF expand step did not succeed.
133    ExpandFailed,
134}
135
136impl core::fmt::Display for HkdfFailureKind {
137    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
138        let detail = match self {
139            HkdfFailureKind::InvalidIkmLength => "invalid input key material length",
140            HkdfFailureKind::InvalidDomainTagLength => "invalid domain tag length",
141            HkdfFailureKind::InvalidDomainTagByte => "invalid domain tag byte",
142            HkdfFailureKind::LengthOverflow => "length overflow",
143            HkdfFailureKind::InvalidOutputLength => "invalid output length",
144            HkdfFailureKind::ExpandFailed => "expand failed",
145        };
146        write!(f, "{detail}")
147    }
148}