• 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

99.02
/src/token/cose/signed/sign1/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 coset::{CoseSign1, CoseSign1Builder, Header};
12

13
use crate::error::CoseCipherError;
14
use crate::token::cose::aad::AadProvider;
15
use crate::token::cose::key::KeyProvider;
16
use crate::token::cose::signed;
17
use crate::token::cose::SignCryptoBackend;
18

19
#[cfg(all(test, feature = "std"))]
20
mod tests;
21

22
/// Extension trait that enables signing using predefined backends instead of by providing signature
23
/// functions.
24
pub trait CoseSign1BuilderExt: Sized {
25
    /// Creates the signature for the CoseSign1 object using the given backend.
26
    ///
27
    /// # Parameters
28
    ///
29
    /// - `backend`      - cryptographic backend to use.
30
    /// - `key_provider` - provider for cryptographic keys to use (if you already know the
31
    ///                    corresponding key, simply provide an immutable borrow of it).
32
    /// - `protected`    - protected headers for the resulting [`CoseSign1`] instance. Will override
33
    ///                    headers previously set using [`CoseSign1Builder::protected`].
34
    /// - `unprotected`  - unprotected headers for the resulting [`CoseSign1`] instance. Will override
35
    ///                    headers previously set using [`CoseSign1Builder::unprotected`].
36
    /// - `external_aad` - provider of additional authenticated data that should be included in the
37
    ///                    signature calculation.
38
    /// # Errors
39
    ///
40
    /// If the COSE structure, selected [`CoseKey`](coset::CoseKey) or AAD (or any combination of those) are malformed
41
    /// or otherwise unsuitable for signature calculation, this function will return the most
42
    /// fitting [`CoseCipherError`] for the specific type of error.
43
    ///
44
    /// If the COSE object is not malformed, but an error in the cryptographic backend occurs, a
45
    /// [`CoseCipherError::Other`] containing the backend error will be returned.
46
    /// Refer to the backend module's documentation for information on the possible errors that may
47
    /// occur.
48
    ///
49
    /// If the COSE object is not malformed, but the key provider does not provide a key, a
50
    /// [`CoseCipherError::NoMatchingKeyFound`] will be returned.
51
    ///
52
    /// # Examples
53
    ///
54
    /// Refer to [the documentation for the CoseSign1 extensions](CoseSign1Ext) for examples.
55
    ///
56
    // TODO: Setting all of these options at once kind of defeats the purpose of
57
    //       the builder pattern, but it is necessary here, as we lack access to the `protected`
58
    //       and `unprotected` headers that were previously set (the field is private).
59
    //       This should be fixed when porting all of this to coset.
60
    fn try_sign<B: SignCryptoBackend, CKP: KeyProvider, CAP: AadProvider>(
61
        self,
62
        backend: &mut B,
63
        key_provider: &CKP,
64
        protected: Option<Header>,
65
        unprotected: Option<Header>,
66
        aad: CAP,
67
    ) -> Result<Self, CoseCipherError<B::Error>>;
68

69
    /// Creates the signature for the CoseSign1 object using the given backend and detached payload.
70
    ///
71
    /// # Parameters
72
    ///
73
    /// - `backend`      - cryptographic backend to use.
74
    /// - `key_provider` - provider for cryptographic keys to use (if you already know the
75
    ///                    corresponding key, simply provide an immutable borrow of it).
76
    /// - `protected`    - protected headers for the resulting [`CoseSign1`] instance. Will override
77
    ///                    headers previously set using [`CoseSign1Builder::protected`].
78
    /// - `unprotected`  - unprotected headers for the resulting [`CoseSign1`] instance. Will override
79
    ///                    headers previously set using [`CoseSign1Builder::unprotected`].
80
    /// - `payload`      - detached payload that should be signed.
81
    /// - `external_aad` - provider of additional authenticated data that should be included in the
82
    ///                    signature calculation.
83
    /// # Errors
84
    ///
85
    /// If the COSE structure, selected [`CoseKey`](coset::CoseKey) or AAD (or any combination of those) are malformed
86
    /// or otherwise unsuitable for signature calculation, this function will return the most
87
    /// fitting [`CoseCipherError`] for the specific type of error.
88
    ///
89
    /// If the COSE object is not malformed, but an error in the cryptographic backend occurs, a
90
    /// [`CoseCipherError::Other`] containing the backend error will be returned.
91
    /// Refer to the backend module's documentation for information on the possible errors that may
92
    /// occur.
93
    ///
94
    /// If the COSE object is not malformed, but the key provider does not provide a key, a
95
    /// [`CoseCipherError::NoMatchingKeyFound`] will be returned.
96
    ///
97
    /// # Examples
98
    ///
99
    /// Refer to [the documentation for the CoseSign1 extensions](CoseSign1Ext) for examples.
100
    // TODO: Setting all of these options at once kind of defeats the purpose of
101
    //       the builder pattern, but it is necessary here, as we lack access to the `protected`
102
    //       and `unprotected` headers that were previously set (the field is private).
103
    //       This should be fixed when porting all of this to coset.
104
    //       This applies to all COSE structures.
105
    fn try_sign_detached<B: SignCryptoBackend, CKP: KeyProvider, CAP: AadProvider>(
106
        self,
107
        backend: &mut B,
108
        key_provider: &CKP,
109
        protected: Option<Header>,
110
        unprotected: Option<Header>,
111
        payload: &[u8],
112
        aad: CAP,
113
    ) -> Result<Self, CoseCipherError<B::Error>>;
114
}
115

116
impl CoseSign1BuilderExt for CoseSign1Builder {
117
    fn try_sign<B: SignCryptoBackend, CKP: KeyProvider, CAP: AadProvider>(
32✔
118
        self,
32✔
119
        backend: &mut B,
32✔
120
        key_provider: &CKP,
32✔
121
        protected: Option<Header>,
32✔
122
        unprotected: Option<Header>,
32✔
123
        aad: CAP,
32✔
124
    ) -> Result<Self, CoseCipherError<B::Error>> {
32✔
125
        let mut builder = self;
32✔
126
        if let Some(protected) = &protected {
32✔
127
            builder = builder.protected(protected.clone());
25✔
128
        }
30✔
129
        if let Some(unprotected) = &unprotected {
32✔
130
            builder = builder.unprotected(unprotected.clone());
32✔
131
        }
32✔
132
        builder.try_create_signature(
32✔
133
            aad.lookup_aad(None, protected.as_ref(), unprotected.as_ref())
32✔
134
                .unwrap_or(&[] as &[u8]),
32✔
135
            |tosign| {
32✔
136
                signed::try_sign(
32✔
137
                    backend,
32✔
138
                    key_provider,
32✔
139
                    protected.as_ref(),
32✔
140
                    unprotected.as_ref(),
32✔
141
                    tosign,
32✔
142
                )
32✔
143
            },
32✔
144
        )
32✔
145
    }
32✔
146
    fn try_sign_detached<B: SignCryptoBackend, CKP: KeyProvider, CAP: AadProvider>(
1✔
147
        self,
1✔
148
        backend: &mut B,
1✔
149
        key_provider: &CKP,
1✔
150
        protected: Option<Header>,
1✔
151
        unprotected: Option<Header>,
1✔
152
        payload: &[u8],
1✔
153
        aad: CAP,
1✔
154
    ) -> Result<Self, CoseCipherError<B::Error>> {
1✔
155
        let mut builder = self;
1✔
156
        if let Some(protected) = &protected {
1✔
157
            builder = builder.protected(protected.clone());
×
158
        }
1✔
159
        if let Some(unprotected) = &unprotected {
1✔
160
            builder = builder.unprotected(unprotected.clone());
1✔
161
        }
1✔
162
        builder.try_create_detached_signature(
1✔
163
            payload,
1✔
164
            aad.lookup_aad(None, protected.as_ref(), unprotected.as_ref())
1✔
165
                .unwrap_or(&[] as &[u8]),
1✔
166
            |tosign| {
1✔
167
                signed::try_sign(
1✔
168
                    backend,
1✔
169
                    key_provider,
1✔
170
                    protected.as_ref(),
1✔
171
                    unprotected.as_ref(),
1✔
172
                    tosign,
1✔
173
                )
1✔
174
            },
1✔
175
        )
1✔
176
    }
1✔
177
}
178

179
/// Extensions to the [`CoseSign1`] type that enable usage of cryptographic backends.
180
///
181
/// # Examples
182
///
183
/// Create a simple [`CoseSign1`] instance that uses the provided key directly and compute a signature
184
/// for it, then verify it:
185
///
186
/// ```
187
///
188
/// use base64::Engine;
1✔
189
/// use coset::{CoseKeyBuilder, CoseRecipientBuilder, CoseSign1Builder, CoseSignatureBuilder, HeaderBuilder, iana};
190
/// use dcaf::error::CoseCipherError;
191
/// use dcaf::token::cose::{CryptoBackend, CoseSign1BuilderExt, CoseSign1Ext};
192
/// use dcaf::token::cose::crypto_impl::openssl::OpensslContext;
193
///
194
/// let mut backend = OpensslContext::new();
195
///
1✔
196
/// let cose_ec2_key_x = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8").unwrap();
1✔
197
/// let cose_ec2_key_y = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4").unwrap();
1✔
198
/// let cose_ec2_key_d = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("V8kgd2ZBRuh2dgyVINBUqpPDr7BOMGcF22CQMIUHtNM").unwrap();
1✔
199
/// let key = CoseKeyBuilder::new_ec2_priv_key(
1✔
200
///                             iana::EllipticCurve::P_256,
1✔
201
///                             cose_ec2_key_x,
1✔
202
///                             cose_ec2_key_y,
1✔
203
///                             cose_ec2_key_d
1✔
204
///                 )
1✔
205
///                 .key_id("example_key".as_bytes().to_vec())
1✔
206
///                 .build();
1✔
207
///
1✔
208
/// let unprotected = HeaderBuilder::new()
1✔
209
///                     .algorithm(iana::Algorithm::ES256)
1✔
210
///                     .key_id("example_key".as_bytes().to_vec())
1✔
211
///                     .build();
1✔
212
///
1✔
213
/// let cose_object = CoseSign1Builder::new()
214
///                     .payload("This is the payload!".as_bytes().to_vec())
1✔
215
///                     .try_sign(&mut backend, &key, None, Some(unprotected), &[] as &[u8])?
1✔
216
///                     .build();
1✔
217
///
1✔
218
/// assert!(cose_object.try_verify(&mut backend, &key, &[] as &[u8]).is_ok());
1✔
219
///
1✔
220
/// # Result::<(), CoseCipherError<<OpensslContext as CryptoBackend>::Error>>::Ok(())
221
/// ```
1✔
222
///
1✔
223
/// Create a simple [`CoseSign1`] instance with a detached payload that uses the provided key directly
224
/// and compute a signature for it, then verify it:
225
///
226
/// ```
227
///
228
/// use base64::Engine;
1✔
229
/// use coset::{CoseKeyBuilder, CoseRecipientBuilder, CoseSign1Builder, CoseSignatureBuilder, HeaderBuilder, iana};
230
/// use dcaf::error::CoseCipherError;
231
/// use dcaf::token::cose::{CryptoBackend, CoseSign1BuilderExt, CoseSign1Ext};
232
/// use dcaf::token::cose::crypto_impl::openssl::OpensslContext;
233
///
234
/// let mut backend = OpensslContext::new();
235
///
1✔
236
/// let cose_ec2_key_x = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8").unwrap();
1✔
237
/// let cose_ec2_key_y = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4").unwrap();
1✔
238
/// let cose_ec2_key_d = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("V8kgd2ZBRuh2dgyVINBUqpPDr7BOMGcF22CQMIUHtNM").unwrap();
1✔
239
/// let key = CoseKeyBuilder::new_ec2_priv_key(
1✔
240
///                             iana::EllipticCurve::P_256,
1✔
241
///                             cose_ec2_key_x,
1✔
242
///                             cose_ec2_key_y,
1✔
243
///                             cose_ec2_key_d
1✔
244
///                 )
1✔
245
///                 .key_id("example_key".as_bytes().to_vec())
1✔
246
///                 .build();
1✔
247
///
1✔
248
/// let unprotected = HeaderBuilder::new()
1✔
249
///                     .algorithm(iana::Algorithm::ES256)
1✔
250
///                     .key_id("example_key".as_bytes().to_vec())
1✔
251
///                     .build();
1✔
252
///
1✔
253
/// let cose_object = CoseSign1Builder::new()
254
///                     .try_sign_detached(&mut backend, &key, None, Some(unprotected), "This is the payload!".as_bytes(), &[] as &[u8])?
1✔
255
///                     .build();
1✔
256
///
1✔
257
/// assert!(cose_object.try_verify_detached(&mut backend, &key, "This is the payload!".as_bytes(), &[] as &[u8]).is_ok());
1✔
258
///
1✔
259
/// # Result::<(), CoseCipherError<<OpensslContext as CryptoBackend>::Error>>::Ok(())
260
/// ```
1✔
261
pub trait CoseSign1Ext {
1✔
262
    /// Attempts to verify the signature using a cryptographic backend.
263
    ///
264
    /// # Parameters
265
    ///
266
    /// - `backend`      - cryptographic backend to use.
267
    /// - `key_provider` - provider for cryptographic keys to use (if you already know the
268
    ///                    corresponding key, simply provide an immutable borrow of it).
269
    /// - `external_aad` - provider of additional authenticated data that should be included in the
270
    ///                    signature calculation.
271
    ///
272
    /// # Errors
273
    ///
274
    /// If the COSE structure, selected [`CoseKey`](coset::CoseKey) or AAD (or any combination of those) are malformed
275
    /// or otherwise unsuitable for signature verification, this function will return the most
276
    /// fitting [`CoseCipherError`] for the specific type of error.
277
    ///
278
    /// If the COSE object is not malformed, but an error in the cryptographic backend occurs, a
279
    /// [`CoseCipherError::Other`] containing the backend error will be returned.
280
    /// Refer to the backend module's documentation for information on the possible errors that may
281
    /// occur.
282
    ///
283
    /// If the COSE object is not malformed, but signature verification fails for all key candidates
284
    /// provided by the key provider a [`CoseCipherError::NoMatchingKeyFound`] will be
285
    /// returned.
286
    ///
287
    /// The error will then contain a list of attempted keys and the corresponding error that led to
288
    /// the verification error for that key.
289
    /// For an invalid signature for an otherwise valid and suitable object+key pairing, this would
290
    /// usually be a [`CoseCipherError::VerificationFailure`].
291
    ///
292
    /// # Examples
293
    ///
294
    /// Verify the example `sign1-tests/sign-pass-01.json` from the `cose-wg/Examples` repository
295
    /// referenced in RFC 9052 using the [`OpensslContext`](super::super::crypto_impl::openssl::OpensslContext)
296
    /// backend:
297
    /// ```
298
    /// use base64::Engine;
1✔
299
    /// use coset::{CoseKeyBuilder, CoseSign1, iana, TaggedCborSerializable};
300
    /// use dcaf::token::cose::{CoseSign1Ext};
301
    /// use dcaf::token::cose::crypto_impl::openssl::OpensslContext;
302
    ///
303
    /// let cose_object_cbor_data = hex::decode("D28441A0A201260442313154546869732069732074686520636F6E74656E742E584087DB0D2E5571843B78AC33ECB2830DF7B6E0A4D5B7376DE336B23C591C90C425317E56127FBE04370097CE347087B233BF722B64072BEB4486BDA4031D27244F").unwrap();
304
    /// let cose_ec2_key_x = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8").unwrap();
1✔
305
    /// let cose_ec2_key_y = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4").unwrap();
1✔
306
    /// let cose_ec2_key_d = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("V8kgd2ZBRuh2dgyVINBUqpPDr7BOMGcF22CQMIUHtNM").unwrap();
1✔
307
    ///
1✔
308
    /// // Parse the object using `coset`.
1✔
309
    /// let cose_object = CoseSign1::from_tagged_slice(cose_object_cbor_data.as_slice()).expect("unable to parse COSE object");
1✔
310
    /// // Create key and AAD as specified in the example.
1✔
311
    /// let key = CoseKeyBuilder::new_ec2_priv_key(iana::EllipticCurve::P_256, cose_ec2_key_x, cose_ec2_key_y, cose_ec2_key_d).build();
1✔
312
    /// let aad: Vec<u8> = Vec::new();
1✔
313
    ///
1✔
314
    /// assert!(
1✔
315
    ///     cose_object.try_verify(
1✔
316
    ///         &mut OpensslContext::new(),
1✔
317
    ///         &mut &key,
1✔
318
    ///         &aad
1✔
319
    ///     ).is_ok()
1✔
320
    /// );
1✔
321
    /// ```
1✔
322
    ///
1✔
323
    /// Attempt to verify the example `sign1-tests/sign-fail-02` from the `cose-wg/Examples`
324
    /// repository referenced in RFC 9052 using the
325
    /// [`OpensslContext`](super::super::crypto_impl::openssl::OpensslContext) backend (should fail, as the
326
    /// signature is invalid):
327
    /// ```
328
    /// use base64::Engine;
1✔
329
    /// use coset::{CoseKeyBuilder, CoseSign, CoseSign1, iana, TaggedCborSerializable};
330
    /// use dcaf::token::cose::crypto_impl::openssl::OpensslContext;
331
    /// use dcaf::error::CoseCipherError;
332
    /// use dcaf::token::cose::CoseSign1Ext;
333
    ///
334
    /// let cose_object_cbor_data =
335
    ///     hex::decode("D28443A10126A10442313154546869732069732074686520636F6E74656E742F58408EB33E4CA31D1C465AB05AAC34CC6B23D58FEF5C083106C4D25A91AEF0B0117E2AF9A291AA32E14AB834DC56ED2A223444547E01F11D3B0916E5A4C345CACB36")
1✔
336
    ///         .unwrap();
1✔
337
    /// let cose_ec2_key_x = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8").unwrap();
1✔
338
    /// let cose_ec2_key_y = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4").unwrap();
1✔
339
    /// let cose_ec2_key_d = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("V8kgd2ZBRuh2dgyVINBUqpPDr7BOMGcF22CQMIUHtNM").unwrap();
1✔
340
    ///
1✔
341
    /// // Parse the object using `coset`.
1✔
342
    /// let cose_object = CoseSign1::from_tagged_slice(
1✔
343
    ///                     cose_object_cbor_data.as_slice()
1✔
344
    ///                   ).expect("unable to parse COSE object");
1✔
345
    /// // Create key and AAD as specified in the example.
1✔
346
    /// let key = CoseKeyBuilder::new_ec2_priv_key(iana::EllipticCurve::P_256, cose_ec2_key_x, cose_ec2_key_y, cose_ec2_key_d).build();
1✔
347
    /// let aad: Vec<u8> = Vec::new();
1✔
348
    ///
1✔
349
    /// assert!(
1✔
350
    ///     matches!(
1✔
351
    ///         cose_object.try_verify(
×
352
    ///             &mut OpensslContext::new(),
1✔
353
    ///             &mut &key,
1✔
354
    ///             &aad
1✔
355
    ///         ),
1✔
356
    ///         Err(CoseCipherError::NoMatchingKeyFound(_))
1✔
357
    ///     )
358
    /// );
359
    /// ```
360
    fn try_verify<B: SignCryptoBackend, CKP: KeyProvider, CAP: AadProvider>(
1✔
361
        &self,
362
        backend: &mut B,
363
        key_provider: &CKP,
364

365
        external_aad: CAP,
366
    ) -> Result<(), CoseCipherError<B::Error>>;
367

368
    /// Attempts to verify the signature of this object and its detached payload using a
369
    /// cryptographic backend.
370
    ///
371
    /// # Parameters
372
    ///
373
    /// - `backend`      - cryptographic backend to use.
374
    /// - `key_provider` - provider for cryptographic keys to use (if you already know the
375
    ///                    corresponding key, simply provide an immutable borrow of it).
376
    /// - `payload`      - detached payload that should be included in signature calculation.
377
    /// - `external_aad` - provider of additional authenticated data that should be included in the
378
    ///                    signature calculation.
379
    ///
380
    /// # Errors
381
    ///
382
    /// If the COSE structure, selected [`CoseKey`](coset::CoseKey) or AAD (or any combination of those) are malformed
383
    /// or otherwise unsuitable for signature verification, this function will return the most
384
    /// fitting [`CoseCipherError`] for the specific type of error.
385
    ///
386
    /// If the COSE object is not malformed, but an error in the cryptographic backend occurs, a
387
    /// [`CoseCipherError::Other`] containing the backend error will be returned.
388
    /// Refer to the backend module's documentation for information on the possible errors that may
389
    /// occur.
390
    ///
391
    /// If the COSE object is not malformed, but signature verification fails for all key candidates
392
    /// provided by the key provider a [`CoseCipherError::NoMatchingKeyFound`] will be
393
    /// returned.
394
    ///
395
    /// The error will then contain a list of attempted keys and the corresponding error that led to
396
    /// the verification error for that key.
397
    /// For an invalid signature for an otherwise valid and suitable object+key pairing, this would
398
    /// usually be a [`CoseCipherError::VerificationFailure`].
399
    ///
400
    /// # Examples
401
    ///
402
    /// Refer to the trait-level documentation for examples.
403
    fn try_verify_detached<B: SignCryptoBackend, CKP: KeyProvider, CAP: AadProvider>(
404
        &self,
405
        backend: &mut B,
406
        key_provider: &CKP,
407

408
        payload: &[u8],
409
        external_aad: CAP,
410
    ) -> Result<(), CoseCipherError<B::Error>>;
411
}
412

413
impl CoseSign1Ext for CoseSign1 {
414
    fn try_verify<B: SignCryptoBackend, CKP: KeyProvider, CAP: AadProvider>(
53✔
415
        &self,
53✔
416
        backend: &mut B,
53✔
417
        key_provider: &CKP,
53✔
418

53✔
419
        external_aad: CAP,
53✔
420
    ) -> Result<(), CoseCipherError<B::Error>> {
53✔
421
        self.verify_signature(
53✔
422
            external_aad
53✔
423
                .lookup_aad(None, Some(&self.protected.header), Some(&self.unprotected))
53✔
424
                .unwrap_or(&[] as &[u8]),
53✔
425
            |signature, toverify| {
53✔
426
                signed::try_verify(
53✔
427
                    backend,
53✔
428
                    key_provider,
53✔
429
                    &self.protected.header,
53✔
430
                    &self.unprotected,
53✔
431
                    signature,
53✔
432
                    toverify,
53✔
433
                )
53✔
434
            },
53✔
435
        )
53✔
436
    }
53✔
437

438
    fn try_verify_detached<'a, 'b, B: SignCryptoBackend, CKP: KeyProvider, CAP: AadProvider>(
1✔
439
        &self,
1✔
440
        backend: &mut B,
1✔
441
        key_provider: &CKP,
1✔
442

1✔
443
        payload: &[u8],
1✔
444
        external_aad: CAP,
1✔
445
    ) -> Result<(), CoseCipherError<B::Error>> {
1✔
446
        self.verify_detached_signature(
1✔
447
            payload,
1✔
448
            external_aad
1✔
449
                .lookup_aad(None, Some(&self.protected.header), Some(&self.unprotected))
1✔
450
                .unwrap_or(&[] as &[u8]),
1✔
451
            |signature, toverify| {
1✔
452
                signed::try_verify(
1✔
453
                    backend,
1✔
454
                    key_provider,
1✔
455
                    &self.protected.header,
1✔
456
                    &self.unprotected,
1✔
457
                    signature,
1✔
458
                    toverify,
1✔
459
                )
1✔
460
            },
1✔
461
        )
1✔
462
    }
1✔
463
}
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