• 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.6
/src/token/cose/encrypted/encrypt/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::rc::Rc;
12
use alloc::vec::Vec;
13
use core::cell::RefCell;
14

15
use coset::{CoseEncrypt, CoseEncryptBuilder, EncryptionContext, Header};
16

17
use crate::error::CoseCipherError;
18
use crate::token::cose::aad::AadProvider;
19
use crate::token::cose::encrypted;
20
use crate::token::cose::encrypted::try_decrypt;
21
use crate::token::cose::encrypted::EncryptCryptoBackend;
22
use crate::token::cose::key::KeyProvider;
23
use crate::token::cose::recipient::{
24
    struct_to_recipient_context, CoseNestedRecipientSearchContext, KeyDistributionCryptoBackend,
25
};
26

27
#[cfg(all(test, feature = "std"))]
28
mod tests;
29

30
/// Extensions to the [`CoseEncryptBuilder`] type that enable usage of cryptographic backends.
31
pub trait CoseEncryptBuilderExt: Sized {
32
    /// Attempts to encrypt the provided payload using a cryptographic backend.
33
    ///
34
    /// Note that you still have to ensure that the key is available to the recipient somehow, i.e.
35
    /// by adding [`CoseRecipient`](coset::CoseRecipient) structures where suitable.
36
    ///
37
    /// # Parameters
38
    ///
39
    /// - `backend`      - cryptographic backend to use.
40
    /// - `key_provider` - provider for cryptographic keys to use (if you already know the
41
    ///                    corresponding key, simply provide an immutable borrow of it).
42
    /// - `protected`    - protected headers for the resulting [`CoseEncrypt`] instance.
43
    ///                    Will override headers previously set using
44
    ///                    [`CoseEncryptBuilder::protected`](CoseEncryptBuilder).
45
    /// - `unprotected`  - unprotected headers for the resulting [`CoseEncrypt`] instance. Will
46
    ///                    override headers previously set using
47
    ///                    [`CoseEncryptBuilder::unprotected`](CoseEncryptBuilder).
48
    /// - `payload`      - payload which should be added to the resulting
49
    ///                    [`CoseEncrypt`](CoseEncrypt) instance in encrypted form.
50
    ///                    Will override a payload previously set using
51
    ///                    [`CoseEncryptBuilder::payload`](CoseEncryptBuilder).
52
    /// - `external_aad` - provider of additional authenticated data that should be included in the
53
    ///                    MAC calculation.
54
    ///
55
    /// # Errors
56
    ///
57
    /// If the COSE structure, selected [`CoseKey`](coset::CoseKey) or AAD (or any combination of
58
    /// those) are malformed or otherwise unsuitable for encryption, this function will return
59
    /// the most fitting [`CoseCipherError`] for the specific type of error.
60
    ///
61
    /// If additional authenticated data is provided even though the chosen algorithm is not an AEAD
62
    /// algorithm, a [`CoseCipherError::AadUnsupported`] will be returned.
63
    ///
64
    /// If the COSE object is not malformed, but an error in the cryptographic backend occurs, a
65
    /// [`CoseCipherError::Other`] containing the backend error will be returned.
66
    /// Refer to the backend module's documentation for information on the possible errors that may
67
    /// occur.
68
    ///
69
    /// If the COSE object is not malformed, but the key provider does not provide a key, a
70
    /// [`CoseCipherError::NoMatchingKeyFound`] will be returned.
71
    ///
72
    /// # Examples
73
    ///
74
    /// Refer to [the documentation for the CoseEncrypt extensions](CoseEncryptExt) for examples.
75
    fn try_encrypt<B: EncryptCryptoBackend, CKP: KeyProvider, CAP: AadProvider>(
76
        self,
77
        backend: &mut B,
78
        key_provider: &CKP,
79
        protected: Option<Header>,
80
        unprotected: Option<Header>,
81
        payload: &[u8],
82
        external_aad: CAP,
83
    ) -> Result<Self, CoseCipherError<B::Error>>;
84
}
85

86
impl CoseEncryptBuilderExt for CoseEncryptBuilder {
87
    fn try_encrypt<B: EncryptCryptoBackend, CKP: KeyProvider, CAP: AadProvider>(
73✔
88
        self,
73✔
89
        backend: &mut B,
73✔
90
        key_provider: &CKP,
73✔
91

73✔
92
        protected: Option<Header>,
73✔
93
        unprotected: Option<Header>,
73✔
94
        payload: &[u8],
73✔
95
        external_aad: CAP,
73✔
96
    ) -> Result<Self, CoseCipherError<B::Error>> {
73✔
97
        let mut builder = self;
73✔
98
        if let Some(protected) = &protected {
73✔
99
            builder = builder.protected(protected.clone());
64✔
100
        }
69✔
101
        if let Some(unprotected) = &unprotected {
73✔
102
            builder = builder.unprotected(unprotected.clone());
73✔
103
        }
73✔
104
        builder.try_create_ciphertext(
73✔
105
            payload,
73✔
106
            external_aad
73✔
107
                .lookup_aad(
73✔
108
                    Some(EncryptionContext::CoseEncrypt),
73✔
109
                    protected.as_ref(),
73✔
110
                    unprotected.as_ref(),
73✔
111
                )
73✔
112
                .unwrap_or(&[] as &[u8]),
73✔
113
            |plaintext, aad| {
73✔
114
                encrypted::try_encrypt(
73✔
115
                    backend,
73✔
116
                    key_provider,
73✔
117
                    protected.as_ref(),
73✔
118
                    unprotected.as_ref(),
73✔
119
                    plaintext,
73✔
120
                    aad,
73✔
121
                )
73✔
122
            },
73✔
123
        )
73✔
124
    }
73✔
125
}
126

127
/// Extensions to the [`CoseEncrypt`] type that enable usage of cryptographic backends.
128
///
129
/// # Examples
130
///
131
/// Create a simple [`CoseEncrypt`] instance that uses the provided key directly and encrypts a
132
/// payload, then decrypt it:
133
///
134
/// ```
135
///
136
/// use coset::{CoseEncryptBuilder, CoseKeyBuilder, CoseRecipientBuilder, HeaderBuilder, iana};
1✔
137
/// use dcaf::error::CoseCipherError;
138
/// use dcaf::token::cose::{CryptoBackend, CoseEncryptBuilderExt, CoseEncryptExt, HeaderBuilderExt};
139
/// use dcaf::token::cose::crypto_impl::openssl::OpensslContext;
140
///
141
/// let mut backend = OpensslContext::new();
142
///
1✔
143
/// let mut key_data = vec![0; 32];
1✔
144
/// backend.generate_rand(key_data.as_mut_slice())?;
1✔
145
/// let key = CoseKeyBuilder::new_symmetric_key(key_data).build();
1✔
146
///
1✔
147
/// let unprotected = HeaderBuilder::new()
148
///                     .algorithm(iana::Algorithm::A256GCM)
1✔
149
///                     .gen_iv(&mut backend, iana::Algorithm::A256GCM)?
1✔
150
///                     .key_id("example_key".as_bytes().to_vec())
1✔
151
///                     .build();
1✔
152
///
1✔
153
/// let recipient = CoseRecipientBuilder::new()
1✔
154
///                     .unprotected(
1✔
155
///                         HeaderBuilder::new()
1✔
156
///                             .algorithm(iana::Algorithm::Direct)
1✔
157
///                             .key_id("example_key".as_bytes().to_vec())
1✔
158
///                             .build()
1✔
159
///                     )
1✔
160
///                     .build();
1✔
161
///
1✔
162
/// let cose_object = CoseEncryptBuilder::new()
163
///                     .add_recipient(recipient)
1✔
164
///                     .try_encrypt(
1✔
165
///                         &mut backend,
1✔
166
///                         &key,
1✔
167
///                         None,
1✔
168
///                         Some(unprotected),
1✔
169
///                         "This is the payload!".as_bytes(),
1✔
170
///                         &[] as &[u8]
1✔
171
///                     )?
1✔
172
///                     .build();
1✔
173
///
1✔
174
/// let plaintext = cose_object.try_decrypt(&mut backend, &key, &[] as &[u8])?;
175
/// assert_eq!(plaintext.as_slice(), "This is the payload!".as_bytes());
1✔
176
///
1✔
177
/// # Result::<(), CoseCipherError<<OpensslContext as CryptoBackend>::Error>>::Ok(())
178
/// ```
1✔
179
///
1✔
180
/// Create a simple [`CoseEncrypt`] instance with recipients that protect a content encryption key
181
/// using AES key wrap. Encrypt a plaintext for it, then verify it:
182
/// ```
183
///
184
/// use coset::{CoseEncryptBuilder, CoseKeyBuilder, CoseRecipientBuilder, EncryptionContext, HeaderBuilder, iana};
1✔
185
/// use dcaf::error::CoseCipherError;
186
/// use dcaf::token::cose::{CryptoBackend, CoseRecipientBuilderExt, CoseEncryptBuilderExt, CoseEncryptExt, HeaderBuilderExt};
187
/// use dcaf::token::cose::crypto_impl::openssl::OpensslContext;
188
///
189
/// let mut backend = OpensslContext::new();
190
///
1✔
191
/// let mut kek_data = vec![0; 32];
1✔
192
/// backend.generate_rand(kek_data.as_mut_slice())?;
1✔
193
/// let kek = CoseKeyBuilder::new_symmetric_key(kek_data).build();
1✔
194
///
1✔
195
/// let mut cek_data = vec![0; 32];
1✔
196
/// backend.generate_rand(cek_data.as_mut_slice())?;
1✔
197
/// let cek = CoseKeyBuilder::new_symmetric_key(cek_data.clone()).build();
1✔
198
///
1✔
199
/// let unprotected = HeaderBuilder::new()
200
///                     .algorithm(iana::Algorithm::A256GCM)
1✔
201
///                     .gen_iv(&mut backend, iana::Algorithm::A256GCM)?
1✔
202
///                     .build();
1✔
203
///
1✔
204
/// let recipient_unprotected = HeaderBuilder::new()
1✔
205
///                             .algorithm(iana::Algorithm::A256KW)
1✔
206
///                             .key_id("example_key".as_bytes().to_vec())
1✔
207
///                             .build();
1✔
208
/// let recipient = CoseRecipientBuilder::new()
1✔
209
///                     .try_encrypt(
1✔
210
///                         &mut backend,
1✔
211
///                         &kek,
1✔
212
///                         EncryptionContext::MacRecipient,
1✔
213
///                         None,
1✔
214
///                         Some(recipient_unprotected),
1✔
215
///                         cek_data.as_slice(),
1✔
216
///                         &[] as &[u8]
1✔
217
///                     )?
1✔
218
///                     .build();
1✔
219
///
1✔
220
/// let cose_object = CoseEncryptBuilder::new()
221
///                     .try_encrypt(
1✔
222
///                         &mut backend,
1✔
223
///                         &cek,
1✔
224
///                         None,
1✔
225
///                         Some(unprotected),
1✔
226
///                         "This is the payload!".as_bytes(),
1✔
227
///                         &[] as &[u8]
1✔
228
///                     )?
1✔
229
///                     .add_recipient(recipient)
1✔
230
///                     .build();
1✔
231
///
1✔
232
/// let plaintext = cose_object.try_decrypt_with_recipients(&mut backend, &kek, &[] as &[u8])?;
233
///
1✔
234
/// assert_eq!(plaintext.as_slice(), "This is the payload!".as_bytes());
235
///
1✔
236
///
237
/// # Result::<(), CoseCipherError<<OpensslContext as CryptoBackend>::Error>>::Ok(())
238
/// ```
1✔
239
pub trait CoseEncryptExt {
1✔
240
    /// Attempts to decrypt the payload contained in this object using a cryptographic backend.
241
    ///
242
    /// Note that [`CoseRecipient`](coset::CoseRecipient)s are not considered for key lookup here,
243
    /// the key provider must provide the key used directly for MAC calculation.
244
    /// If your key provider can/should be able to provide the key for a contained
245
    /// [`CoseRecipient`](coset::CoseRecipient), not for the [`CoseEncrypt`] instance itself, use
246
    /// [`CoseEncrypt::try_decrypt_with_recipients`] instead.
247
    ///
248
    /// # Parameters
249
    ///
250
    /// - `backend`      - cryptographic backend to use.
251
    /// - `key_provider` - provider for cryptographic keys to use (if you already know the
252
    ///                    corresponding key, simply provide an immutable borrow of it).
253
    /// - `external_aad` - provider of additional authenticated data that should be authenticated
254
    ///                    while decrypting (only for AEAD algorithms).
255
    ///
256
    /// # Errors
257
    ///
258
    /// If the COSE structure, selected [`CoseKey`](coset::CoseKey) or AAD (or any combination of
259
    /// those) are malformed or otherwise unsuitable for encryption, this function will return
260
    /// the most fitting [`CoseCipherError`] for the specific type of error.
261
    ///
262
    /// If additional authenticated data is provided even though the chosen algorithm is not an AEAD
263
    /// algorithm, a [`CoseCipherError::AadUnsupported`] will be returned.
264
    ///
265
    /// If the COSE object is not malformed, but an error in the cryptographic backend occurs, a
266
    /// [`CoseCipherError::Other`] containing the backend error will be returned.
267
    /// Refer to the backend module's documentation for information on the possible errors that may
268
    /// occur.
269
    ///
270
    /// If the COSE object is not malformed, but decryption fails for all key candidates provided by
271
    /// the key provider a [`CoseCipherError::NoMatchingKeyFound`] error will be returned.
272
    ///
273
    /// The error will then contain a list of attempted keys and the corresponding error that led to
274
    /// the verification error for that key.
275
    /// For an invalid encrypted payload or AAD for an otherwise valid and suitable object+key
276
    ///  pairing, this would usually be a [`CoseCipherError::VerificationFailure`].
277
    ///
278
    /// # Examples
279
    ///
280
    /// Verify the example `enveloped-tests/env-pass-01.json` from the `cose-wg/Examples` repository
281
    /// referenced in RFC 9052 using the
282
    /// [`OpensslContext`](super::super::crypto_impl::openssl::OpensslContext) backend:
283
    /// ```
284
    /// use base64::Engine;
1✔
285
    /// use coset::{CoseEncrypt, CoseKeyBuilder, TaggedCborSerializable};
286
    /// use dcaf::token::cose::CoseEncryptExt;
287
    /// use dcaf::token::cose::crypto_impl::openssl::OpensslContext;
288
    ///
289
    /// let cose_object_cbor_data = hex::decode("D8608441A0A20101054C02D1F7E6F26C43D4868D87CE582460973A94BB2898009EE52ECFD9AB1DD25867374B9874993C63B0382A855573F0990CD18E818340A20125044A6F75722D73656372657440").unwrap();
290
    /// let cose_symmetric_key_k = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("hJtXIZ2uSN5kbQfbtTNWbg").unwrap();
1✔
291
    ///
1✔
292
    /// // Parse the object using `coset`.
1✔
293
    /// let cose_object = CoseEncrypt::from_tagged_slice(cose_object_cbor_data.as_slice()).expect("unable to parse COSE object");
1✔
294
    /// // Create key and AAD as specified in the example.
1✔
295
    /// let key = CoseKeyBuilder::new_symmetric_key(cose_symmetric_key_k).build();
1✔
296
    /// let aad: Vec<u8> = Vec::new();
1✔
297
    ///
1✔
298
    /// assert!(
1✔
299
    ///     cose_object.try_decrypt(
1✔
300
    ///         &mut OpensslContext::new(),
1✔
301
    ///         &mut &key,
1✔
302
    ///         &aad
1✔
303
    ///     ).is_ok()
1✔
304
    /// );
1✔
305
    /// ```
1✔
306
    ///
1✔
307
    /// Attempt to verify the example `enveloped-tests/env-fail-02` from the `cose-wg/Examples`
308
    /// repository referenced in RFC 9052 using the
309
    /// [`OpensslContext`](super::super::crypto_impl::openssl::OpensslContext) backend (should fail,
310
    /// as the ciphertext is invalid):
311
    /// ```
312
    /// use base64::Engine;
1✔
313
    /// use coset::{CoseEncrypt, CoseKeyBuilder, TaggedCborSerializable};
314
    /// use dcaf::token::cose::CoseEncryptExt;
315
    /// use dcaf::token::cose::crypto_impl::openssl::OpensslContext;
316
    /// use dcaf::error::CoseCipherError;
317
    ///
318
    /// let cose_object_cbor_data =
319
    ///     hex::decode("D8608443A10101A1054C02D1F7E6F26C43D4868D87CE582460973A94BB2898009EE52ECFD9AB1DD25867374B3581F2C80039826350B97AE2300E42FD818340A20125044A6F75722D73656372657440")
1✔
320
    ///         .unwrap();
1✔
321
    /// let cose_symmetric_key_k =
1✔
322
    ///     base64::engine::general_purpose::URL_SAFE_NO_PAD
1✔
323
    ///         .decode("hJtXIZ2uSN5kbQfbtTNWbg")
1✔
324
    ///         .unwrap();
1✔
325
    ///
1✔
326
    /// // Parse the object using `coset`.
1✔
327
    /// let cose_object = CoseEncrypt::from_tagged_slice(
1✔
328
    ///                     cose_object_cbor_data.as_slice()
1✔
329
    ///                   ).expect("unable to parse COSE object");
1✔
330
    /// // Create key and AAD as specified in the example.
1✔
331
    /// let key = CoseKeyBuilder::new_symmetric_key(cose_symmetric_key_k).build();
1✔
332
    /// let aad: Vec<u8> = Vec::new();
1✔
333
    ///
1✔
334
    /// assert!(
1✔
335
    ///     matches!(
1✔
336
    ///         cose_object.try_decrypt(
×
337
    ///             &mut OpensslContext::new(),
1✔
338
    ///             &mut &key,
1✔
339
    ///             &aad
1✔
340
    ///         ),
1✔
341
    ///         Err(CoseCipherError::NoMatchingKeyFound(_))
1✔
342
    ///     )
343
    /// );
344
    /// ```
345
    fn try_decrypt<B: EncryptCryptoBackend, CKP: KeyProvider, CAP: AadProvider>(
1✔
346
        &self,
347
        backend: &mut B,
348
        key_provider: &CKP,
349

350
        external_aad: CAP,
351
    ) -> Result<Vec<u8>, CoseCipherError<B::Error>>;
352

353
    /// Attempts to decrypt the payload contained in this object using a cryptographic backend,
354
    /// performing a search through the contained [`CoseRecipient`](coset::CoseRecipient)s in order
355
    /// to decrypt the content encryption key (CEK).
356
    ///
357
    /// Note: As of now, if a recipient of type [`iana::Algorithm::Direct`](coset::iana::Algorithm::Direct)
358
    /// is present, there is no check to ensure that `Direct` is the only method used on the message
359
    /// (RFC 9052, Section 8.5.1).
360
    /// If you _need_ to ensure this, you must implement this check on your own.
361
    ///
362
    /// # Parameters
363
    ///
364
    /// - `backend`      - cryptographic backend to use.
365
    /// - `key_provider` - provider for cryptographic keys to use (if you already know the
366
    ///                    corresponding key, simply provide an immutable borrow of it).
367
    /// - `external_aad` - provider of additional authenticated data that should be authenticated
368
    ///                    while decrypting (only for AEAD algorithms).
369
    ///
370
    /// # Errors
371
    ///
372
    /// If the COSE structure, selected [`CoseKey`](coset::CoseKey) or AAD (or any combination of those) are malformed
373
    /// or otherwise unsuitable for decryption, this function will return the most fitting
374
    /// [`CoseCipherError`] for the specific type of error.
375
    ///
376
    /// If additional authenticated data is provided even though the chosen algorithm is not an AEAD
377
    /// algorithm, a [`CoseCipherError::AadUnsupported`] will be returned.
378
    ///
379
    /// If the COSE object is not malformed, but an error in the cryptographic backend occurs, a
380
    /// [`CoseCipherError::Other`] containing the backend error will be returned.
381
    /// Refer to the backend module's documentation for information on the possible errors that may
382
    /// occur.
383
    ///
384
    /// If the COSE object itself is not malformed, but decryption of all [`CoseRecipient`](coset::CoseRecipient)s fails
385
    /// (due to non-available keys or malformation), [`CoseCipherError::NoDecryptableRecipientFound`]
386
    /// is returned with a list of the attempted recipients and resulting errors.
387
    ///
388
    /// Note that not all recipients will necessarily be tried, as a malformed [`CoseRecipient`](coset::CoseRecipient) will
389
    /// terminate the recipient search early.
390
    ///
391
    /// The error will then contain a list of attempted keys and the corresponding error that led to
392
    /// the verification error for that key.
393
    /// For an invalid encrypted payload or AAD for an otherwise valid and suitable object+key
394
    /// pairing, this would usually be a [`CoseCipherError::VerificationFailure`].
395
    ///
396
    /// # Examples
397
    ///
398
    /// Verify the example `aes-wrap-examples/aes-wrap-128-04.json` from the `cose-wg/Examples`
399
    /// repository referenced in RFC 9052 using the
400
    /// [`OpensslContext`](super::super::crypto_impl::openssl::OpensslContext) backend:
401
    /// ```
402
    /// use base64::Engine;
1✔
403
    /// use coset::{CoseEncrypt, CoseKeyBuilder, CoseMac, TaggedCborSerializable};
404
    /// use dcaf::error::CoseCipherError;
405
    /// use dcaf::token::cose::{CryptoBackend, CoseEncryptExt, CoseMacExt};
406
    /// use dcaf::token::cose::crypto_impl::openssl::OpensslContext;
407
    ///
408
    /// let cose_object_cbor_data = hex::decode("D8608443A10101A1054CDDDC08972DF9BE62855291A158246F5556D71834CD1BD3FDCBFFF28CFA0F7D598C138D23B40C225AF5E3F2096A46C766813D818340A20122044A6F75722D7365637265745818112872F405A5AC48A2EDE46AC20E93E3D3A38B9762D0A3E8").unwrap();
409
    /// let cose_symmetric_key_k = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("hJtXIZ2uSN5kbQfbtTNWbg").unwrap();
1✔
410
    ///
1✔
411
    /// // Parse the object using `coset`.
1✔
412
    /// let cose_object = CoseEncrypt::from_tagged_slice(cose_object_cbor_data.as_slice()).expect("unable to parse COSE object");
1✔
413
    /// // Create key and AAD as specified in the example.
1✔
414
    /// let key = CoseKeyBuilder::new_symmetric_key(cose_symmetric_key_k).build();
1✔
415
    /// let aad: Vec<u8> = Vec::new();
1✔
416
    ///
1✔
417
    /// let plaintext = cose_object.try_decrypt_with_recipients(
418
    ///                     &mut OpensslContext::new(),
1✔
419
    ///                     &mut &key,
1✔
420
    ///                     &aad
1✔
421
    ///                 )?;
1✔
422
    ///
1✔
423
    /// assert_eq!(plaintext.as_slice(), "This is the content.".as_bytes());
424
    ///
1✔
425
    /// # Result::<(), CoseCipherError<<OpensslContext as CryptoBackend>::Error>>::Ok(())
426
    /// ```
1✔
427
    fn try_decrypt_with_recipients<
1✔
428
        B: KeyDistributionCryptoBackend + EncryptCryptoBackend,
429
        CKP: KeyProvider,
430
        CAP: AadProvider,
431
    >(
432
        &self,
433
        backend: &mut B,
434
        key_provider: &CKP,
435
        external_aad: CAP,
436
    ) -> Result<Vec<u8>, CoseCipherError<B::Error>>;
437
}
438

439
impl CoseEncryptExt for CoseEncrypt {
440
    fn try_decrypt<B: EncryptCryptoBackend, CKP: KeyProvider, CAP: AadProvider>(
5✔
441
        &self,
5✔
442
        backend: &mut B,
5✔
443
        key_provider: &CKP,
5✔
444
        external_aad: CAP,
5✔
445
    ) -> Result<Vec<u8>, CoseCipherError<B::Error>> {
5✔
446
        let backend = Rc::new(RefCell::new(backend));
5✔
447
        self.decrypt(
5✔
448
            external_aad
5✔
449
                .lookup_aad(
5✔
450
                    Some(EncryptionContext::CoseEncrypt),
5✔
451
                    Some(&self.protected.header),
5✔
452
                    Some(&self.unprotected),
5✔
453
                )
5✔
454
                .unwrap_or(&[] as &[u8]),
5✔
455
            |ciphertext, aad| {
5✔
456
                try_decrypt(
5✔
457
                    &backend,
5✔
458
                    key_provider,
5✔
459
                    &self.protected.header,
5✔
460
                    &self.unprotected,
5✔
461
                    ciphertext,
5✔
462
                    aad,
5✔
463
                )
5✔
464
            },
5✔
465
        )
5✔
466
    }
5✔
467

468
    fn try_decrypt_with_recipients<
125✔
469
        B: KeyDistributionCryptoBackend + EncryptCryptoBackend,
125✔
470
        CKP: KeyProvider,
125✔
471
        CAP: AadProvider,
125✔
472
    >(
125✔
473
        &self,
125✔
474
        backend: &mut B,
125✔
475
        key_provider: &CKP,
125✔
476
        external_aad: CAP,
125✔
477
    ) -> Result<Vec<u8>, CoseCipherError<B::Error>> {
125✔
478
        let backend = Rc::new(RefCell::new(backend));
125✔
479
        let nested_recipient_key_provider = CoseNestedRecipientSearchContext::new(
125✔
480
            &self.recipients,
125✔
481
            Rc::clone(&backend),
125✔
482
            key_provider,
125✔
483
            &external_aad,
125✔
484
            struct_to_recipient_context(EncryptionContext::CoseEncrypt),
125✔
485
        );
125✔
486
        match self.decrypt(
125✔
487
            external_aad
125✔
488
                .lookup_aad(
125✔
489
                    Some(EncryptionContext::CoseEncrypt),
125✔
490
                    Some(&self.protected.header),
125✔
491
                    Some(&self.unprotected),
125✔
492
                )
125✔
493
                .unwrap_or(&[] as &[u8]),
125✔
494
            |ciphertext, aad| {
125✔
495
                try_decrypt(
125✔
496
                    &backend,
125✔
497
                    &nested_recipient_key_provider,
125✔
498
                    &self.protected.header,
125✔
499
                    &self.unprotected,
125✔
500
                    ciphertext,
125✔
501
                    aad,
125✔
502
                )
125✔
503
            },
125✔
504
        ) {
125✔
505
            Err(CoseCipherError::NoMatchingKeyFound(cek_errors)) => {
20✔
506
                Err(CoseCipherError::NoDecryptableRecipientFound(
20✔
507
                    nested_recipient_key_provider.into_errors(),
20✔
508
                    cek_errors,
20✔
509
                ))
20✔
510
            }
511
            v => v,
105✔
512
        }
513
    }
125✔
514
}
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