• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

namib-project / dcaf-rs / 11935120896

20 Nov 2024 02:11PM UTC coverage: 86.555% (+1.3%) from 85.242%
11935120896

Pull #27

github

web-flow
Merge d2b3d706b into 383248641
Pull Request #27: ci: update grcov to latest stable version

6116 of 7066 relevant lines covered (86.56%)

167.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

60.29
/src/token/cose/maced/mod.rs
1
/*
2
 * Copyright (c) 2024 The NAMIB Project Developers.
3
 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4
 * https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5
 * <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6
 * option. This file may not be copied, modified, or distributed
7
 * except according to those terms.
8
 *
9
 * SPDX-License-Identifier: MIT OR Apache-2.0
10
 */
11
use alloc::collections::BTreeSet;
12
use alloc::rc::Rc;
13
use alloc::vec::Vec;
14
use core::cell::RefCell;
15

16
use coset::{iana, Algorithm, Header, KeyOperation};
17

18
pub use mac::{CoseMacBuilderExt, CoseMacExt};
19
pub use mac0::{CoseMac0BuilderExt, CoseMac0Ext};
20

21
use crate::error::CoseCipherError;
22
use crate::token::cose::key::{CoseParsedKey, CoseSymmetricKey, KeyProvider};
23
use crate::token::cose::util::{ensure_valid_hmac_key, try_cose_crypto_operation};
24
use crate::token::cose::CryptoBackend;
25

26
mod mac;
27
mod mac0;
28

29
/// Trait for cryptographic backends that can perform Message Authentication Code (MAC) computation
30
/// and verification operations for algorithms used in COSE structures.
31
pub trait MacCryptoBackend: CryptoBackend {
32
    /// Computes an HMAC for the given `payload` using the given `algorithm` and `key`.
33
    ///
34
    /// The MAC should be computed with the padding specified in RFC 2104 (as described in RFC 9053,
35
    /// Section 3.1).
36
    ///
37
    /// # Arguments
38
    ///
39
    /// * `algorithm` - The HMAC variant to use (determines the hash function).
40
    ///           If unsupported by the backend, a [`CoseCipherError::UnsupportedAlgorithm`] error
41
    ///           should be returned.
42
    ///           If the given algorithm is an IANA-assigned value that is unknown, the
43
    ///           implementation should return [`CoseCipherError::UnsupportedAlgorithm`] (in case
44
    ///           additional variants of HMAC are ever added).
45
    ///           If the algorithm is not an HMAC algorithm, the implementation may return
46
    ///           [`CoseCipherError::UnsupportedAlgorithm`] or panic.
47
    /// * `key` - Symmetric key that should be used.
48
    ///           Implementations may assume that the provided key has the right length for the
49
    ///           provided algorithm, and panic if this is not the case.
50
    /// * `payload` - Data for which the MAC should be calculated.
51
    ///
52
    /// # Returns
53
    ///
54
    /// It is expected that the return value is a MAC conforming to RFC 9053, Section 3.1, i.e. the
55
    /// return value should be the computed MAC bytes as a `Vec`.
56
    ///
57
    /// # Errors
58
    ///
59
    /// In case of errors, the implementation may return any valid [`CoseCipherError`].
60
    /// For backend-specific errors, [`CoseCipherError::Other`] may be used to convey a
61
    /// backend-specific error.
62
    ///
63
    /// # Panics
64
    ///
65
    /// Implementations may panic if the provided algorithm is not an HMAC algorithm, the
66
    /// provided key is not of the right length for the provided algorithm or if an unrecoverable
67
    /// backend error occurs that necessitates a panic (at their own discretion).
68
    /// In the last of the above cases, additional panics should be documented on the backend level.
69
    ///
70
    /// For unknown algorithms or key curves, however, the implementation must not panic and return
71
    /// [`CoseCipherError::UnsupportedAlgorithm`] instead (in case new HMAC variants are ever
72
    /// defined).
73
    #[allow(unused_variables)]
74
    fn compute_hmac(
×
75
        &mut self,
×
76
        algorithm: iana::Algorithm,
×
77
        key: CoseSymmetricKey<'_, Self::Error>,
×
78
        payload: &[u8],
×
79
    ) -> Result<Vec<u8>, CoseCipherError<Self::Error>> {
×
80
        Err(CoseCipherError::UnsupportedAlgorithm(Algorithm::Assigned(
×
81
            algorithm,
×
82
        )))
×
83
    }
×
84

85
    /// Verifies the HMAC provided as `tag` for the given `payload` using the given `algorithm` and
86
    /// `key`.
87
    ///
88
    /// The MAC should be computed with the padding specified in RFC 2104 (as described in RFC 9053,
89
    /// Section 3.1).
90
    ///
91
    /// The HMAC comparison must be performed using a comparison function that is resistant to
92
    /// timing attacks.
93
    ///
94
    /// # Arguments
95
    ///
96
    /// * `algorithm` - The HMAC variant to use (determines the hash function).
97
    ///           If unsupported by the backend, a [`CoseCipherError::UnsupportedAlgorithm`] error
98
    ///           should be returned.
99
    ///           If the given algorithm is an IANA-assigned value that is unknown, the
100
    ///           implementation should return [`CoseCipherError::UnsupportedAlgorithm`] (in case
101
    ///           additional variants of HMAC are ever added).
102
    ///           If the algorithm is not an HMAC algorithm, the implementation may return
103
    ///           [`CoseCipherError::UnsupportedAlgorithm`] or panic.
104
    /// * `key` - Symmetric key that should be used.
105
    ///           Implementations may assume that the provided key has the right length for the
106
    ///           provided algorithm, and panic if this is not the case.
107
    /// * `payload` - Data for which the MAC should be calculated.
108
    ///
109
    /// # Returns
110
    ///
111
    /// It is expected that the return value is `Ok(())` if the computed MAC matches the one
112
    /// provided, or a [`CoseCipherError::VerificationFailure`] if it doesn't even though MAC
113
    /// computation was successful.
114
    ///
115
    /// # Errors
116
    ///
117
    /// In case of errors, the implementation may return any valid [`CoseCipherError`].
118
    /// For backend-specific errors, [`CoseCipherError::Other`] may be used to convey a
119
    /// backend-specific error.
120
    ///
121
    /// # Panics
122
    ///
123
    /// Implementations may panic if the provided algorithm is not an HMAC algorithm, the
124
    /// provided key is not of the right length for the provided algorithm or if an unrecoverable
125
    /// backend error occurs that necessitates a panic (at their own discretion).
126
    /// In the last of the above cases, additional panics should be documented on the backend level.
127
    ///
128
    /// For unknown algorithms or key curves, however, the implementation must not panic and return
129
    /// [`CoseCipherError::UnsupportedAlgorithm`] instead (in case new HMAC variants are ever
130
    /// defined).
131
    #[allow(unused_variables)]
132
    fn verify_hmac(
×
133
        &mut self,
×
134
        algorithm: iana::Algorithm,
×
135
        key: CoseSymmetricKey<'_, Self::Error>,
×
136
        tag: &[u8],
×
137
        payload: &[u8],
×
138
    ) -> Result<(), CoseCipherError<Self::Error>> {
×
139
        Err(CoseCipherError::UnsupportedAlgorithm(Algorithm::Assigned(
×
140
            algorithm,
×
141
        )))
×
142
    }
×
143
}
144

145
/// Attempts to perform a COSE HMAC computation operation for a [`CoseMac`](coset::CoseMac) or
146
/// [`CoseMac0`](coset::CoseMac0) structure with the given `protected` and `unprotected`
147
/// headers and `payload` using the given `backend` and `key_provider`.
148
///
149
/// Also performs checks that ensure that the given parameters (esp. headers and keys) are valid and
150
/// are coherent with each other.
151
///
152
/// If the `key_provider` returns multiple keys, all will be tried until one can be successfully
153
/// used for the given operation.
154
fn try_compute<B: MacCryptoBackend, CKP: KeyProvider>(
63✔
155
    backend: &mut B,
63✔
156
    key_provider: &CKP,
63✔
157
    protected: Option<&Header>,
63✔
158
    unprotected: Option<&Header>,
63✔
159
    payload: &[u8],
63✔
160
) -> Result<Vec<u8>, CoseCipherError<B::Error>> {
63✔
161
    try_cose_crypto_operation(
63✔
162
        key_provider,
63✔
163
        protected,
63✔
164
        unprotected,
63✔
165
        BTreeSet::from_iter(vec![KeyOperation::Assigned(iana::KeyOperation::MacCreate)]),
63✔
166
        |key, alg, _protected, _unprotected| {
63✔
167
            let parsed_key = CoseParsedKey::try_from(key)?;
63✔
168

169
            match alg {
63✔
170
                iana::Algorithm::HMAC_256_256
171
                | iana::Algorithm::HMAC_384_384
172
                | iana::Algorithm::HMAC_512_512 => {
173
                    let symm_key = ensure_valid_hmac_key(alg, parsed_key)?;
63✔
174
                    backend.compute_hmac(alg, symm_key, payload)
63✔
175
                }
176
                alg => Err(CoseCipherError::UnsupportedAlgorithm(Algorithm::Assigned(
×
177
                    alg,
×
178
                ))),
×
179
            }
180
        },
63✔
181
    )
63✔
182
}
63✔
183

184
/// Attempts to perform a COSE HMAC verification operation for a [`CoseMac`](coset::CoseMac) or
185
/// [`CoseMac0`](coset::CoseMac0) structure with the given `protected` and `unprotected`
186
/// headers and `payload` using the given `backend` and `key_provider`.
187
///
188
/// Also performs checks that ensure that the given parameters (esp. headers and keys) are valid and
189
/// are coherent with each other.
190
///
191
/// If the `key_provider` returns multiple keys, all will be tried until one can be successfully
192
/// used for the given operation.
193
pub(crate) fn try_verify<B: MacCryptoBackend, CKP: KeyProvider>(
111✔
194
    backend: &Rc<RefCell<&mut B>>,
111✔
195
    key_provider: &CKP,
111✔
196
    protected: &Header,
111✔
197
    unprotected: &Header,
111✔
198
    tag: &[u8],
111✔
199
    payload: &[u8],
111✔
200
) -> Result<(), CoseCipherError<B::Error>> {
111✔
201
    try_cose_crypto_operation(
111✔
202
        key_provider,
111✔
203
        Some(protected),
111✔
204
        Some(unprotected),
111✔
205
        BTreeSet::from_iter(vec![KeyOperation::Assigned(iana::KeyOperation::MacVerify)]),
111✔
206
        |key, alg, _protected, _unprotected| {
111✔
207
            let parsed_key = CoseParsedKey::try_from(key)?;
103✔
208

209
            match alg {
103✔
210
                iana::Algorithm::HMAC_256_256
211
                | iana::Algorithm::HMAC_384_384
212
                | iana::Algorithm::HMAC_512_512 => {
213
                    let symm_key = ensure_valid_hmac_key(alg, parsed_key)?;
103✔
214
                    (*backend.borrow_mut()).verify_hmac(alg, symm_key, tag, payload)
103✔
215
                }
216
                alg => Err(CoseCipherError::UnsupportedAlgorithm(Algorithm::Assigned(
×
217
                    alg,
×
218
                ))),
×
219
            }
220
        },
111✔
221
    )
111✔
222
}
111✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc