Skip to main content

api_impl/
crypto.rs

1// Copyright 2025 The Fuchsia Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::cell::{RefCell, RefMut};
6use std::cmp::min;
7use std::collections::HashMap;
8use std::iter;
9use std::marker::PhantomData;
10use std::rc::Rc;
11
12use aes::cipher::{self, KeyInit, KeyIvInit};
13use aes::{Aes128, Aes192, Aes256};
14use cbc::{Decryptor as CbcDecryptor, Encryptor as CbcEncryptor};
15use cmac::Cmac;
16use ecb::{Decryptor as EcbDecryptor, Encryptor as EcbEncryptor};
17use hmac::Hmac;
18use rsa::rand_core::{self, CryptoRng, RngCore};
19use rsa::traits::{
20    PaddingScheme as RsaPaddingScheme, PublicKeyParts as _, SignatureScheme as RsaSignatureScheme,
21};
22use rsa::{Oaep, Pss, RsaPrivateKey};
23use sha1::digest::DynDigest as Digest;
24use sha1::{Sha1, digest};
25use sha2::{Sha224, Sha256, Sha384, Sha512};
26use tee_internal::{
27    Algorithm, Attribute, EccCurve, Error, Mode, OperationHandle, Result as TeeResult, Usage,
28};
29
30use crate::ErrorWithSize;
31use crate::storage::{
32    AesKey, HmacSha1Key, HmacSha224Key, HmacSha256Key, HmacSha384Key, HmacSha512Key, Key,
33    KeyType as _, NoKey, Object, RsaKeypair,
34};
35
36type AesCmac128 = Cmac<Aes128>;
37type AesCmac192 = Cmac<Aes192>;
38type AesCmac256 = Cmac<Aes256>;
39type HmacSha1 = Hmac<Sha1>;
40type HmacSha224 = Hmac<Sha224>;
41type HmacSha256 = Hmac<Sha256>;
42type HmacSha384 = Hmac<Sha384>;
43type HmacSha512 = Hmac<Sha512>;
44
45pub fn is_algorithm_supported(alg: Algorithm, element: EccCurve) -> bool {
46    if element != EccCurve::None {
47        return false;
48    }
49    match alg {
50        Algorithm::Sha1
51        | Algorithm::Sha224
52        | Algorithm::Sha256
53        | Algorithm::Sha384
54        | Algorithm::Sha512
55        | Algorithm::AesCbcNopad
56        | Algorithm::AesEcbNopad
57        | Algorithm::AesCmac
58        | Algorithm::HmacSha1
59        | Algorithm::HmacSha224
60        | Algorithm::HmacSha256
61        | Algorithm::HmacSha384
62        | Algorithm::HmacSha512
63        | Algorithm::RsaesPkcs1OaepMgf1Sha1 => true,
64        _ => false,
65    }
66}
67
68// An RNG abstraction in the shape expected by RustCrypto APIs.
69pub(crate) struct Rng {}
70
71impl RngCore for Rng {
72    fn next_u32(&mut self) -> u32 {
73        rand_core::impls::next_u32_via_fill(self)
74    }
75
76    fn next_u64(&mut self) -> u64 {
77        rand_core::impls::next_u64_via_fill(self)
78    }
79
80    fn fill_bytes(&mut self, dest: &mut [u8]) {
81        zx::cprng_draw(dest)
82    }
83
84    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
85        self.fill_bytes(dest);
86        Ok(())
87    }
88}
89
90impl CryptoRng for Rng {}
91
92impl p256::elliptic_curve::rand_core::TryRng for Rng {
93    type Error = p256::elliptic_curve::rand_core::Infallible;
94
95    fn try_next_u32(&mut self) -> Result<u32, Self::Error> {
96        Ok(self.next_u32())
97    }
98
99    fn try_next_u64(&mut self) -> Result<u64, Self::Error> {
100        Ok(self.next_u64())
101    }
102
103    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Self::Error> {
104        self.fill_bytes(dest);
105        Ok(())
106    }
107}
108
109impl p256::elliptic_curve::rand_core::TryCryptoRng for Rng {}
110
111// A MAC abstraction conveniently shaped for our API glue needs.
112trait Mac {
113    fn output_size(&self) -> usize;
114
115    fn update(&mut self, data: &[u8]);
116
117    fn reset(&mut self);
118
119    fn finalize_into_reset(&mut self, out: &mut [u8]);
120
121    // Returns Error::MacInvalid in the case of failure.
122    fn verify_reset(&mut self, expected: &[u8]) -> TeeResult;
123}
124
125// Implementations for the hmac digest types.
126macro_rules! impl_hmac_mac {
127    ($($t:ty),*) => {
128        $(
129            impl Mac for Hmac<$t> {
130                fn output_size(&self) -> usize {
131                    <Self as digest::OutputSizeUser>::output_size()
132                }
133
134                fn update(&mut self, data: &[u8]) {
135                    <Self as digest::Update>::update(self, data)
136                }
137
138                fn reset(&mut self) {
139                    <Self as digest::Reset>::reset(self)
140                }
141
142                fn finalize_into_reset(&mut self, out: &mut [u8]) {
143                    <Self as digest::FixedOutputReset>::finalize_into_reset(self, out.into())
144                }
145
146                fn verify_reset(&mut self, expected: &[u8]) -> TeeResult {
147                    let finalized = <Self as digest::FixedOutputReset>::finalize_fixed_reset(self);
148                    if finalized.as_slice() == expected { Ok(()) } else { Err(Error::MacInvalid) }
149                }
150            }
151        )*
152    };
153}
154impl_hmac_mac!(Sha1, Sha224, Sha256, Sha384, Sha512);
155
156macro_rules! impl_cmac_mac {
157    ($($t:ty),*) => {
158        $(
159            impl Mac for Cmac<$t> {
160                fn output_size(&self) -> usize {
161                    <Self as cmac::digest::OutputSizeUser>::output_size()
162                }
163
164                fn update(&mut self, data: &[u8]) {
165                    <Self as cmac::digest::Update>::update(self, data)
166                }
167
168                fn reset(&mut self) {
169                    <Self as cmac::digest::Reset>::reset(self)
170                }
171
172                fn finalize_into_reset(&mut self, out: &mut [u8]) {
173                    <Self as cmac::digest::FixedOutputReset>::finalize_into_reset(self, out.try_into().unwrap())
174                }
175
176                fn verify_reset(&mut self, expected: &[u8]) -> TeeResult {
177                    let finalized = <Self as cmac::digest::FixedOutputReset>::finalize_fixed_reset(self);
178                    if finalized.as_slice() == expected { Ok(()) } else { Err(Error::MacInvalid) }
179                }
180            }
181        )*
182    };
183}
184impl_cmac_mac!(Aes128, Aes192, Aes256);
185
186// Supported MAC algorithm types.
187enum MacType {
188    AesCmac,
189    HmacSha1,
190    HmacSha224,
191    HmacSha256,
192    HmacSha384,
193    HmacSha512,
194}
195
196// A cipher abstraction conveniently shaped for our API glue needs.
197trait Cipher {
198    fn block_size(&self) -> usize;
199    fn set_iv(&mut self, iv: &[u8]);
200    fn reset(&mut self);
201    fn encrypt(&self, input: &[u8], output: &mut [u8]);
202    fn encrypt_in_place(&self, inout: &mut [u8]);
203    fn decrypt(&self, input: &[u8], output: &mut [u8]);
204    fn decrypt_in_place(&self, inout: &mut [u8]);
205}
206
207impl<C: PreCipher> Cipher for C {
208    fn set_iv(&mut self, iv: &[u8]) {
209        self.set_iv(iv)
210    }
211
212    fn reset(&mut self) {
213        self.reset()
214    }
215
216    fn block_size(&self) -> usize {
217        debug_assert_eq!(C::Encryptor::block_size(), C::Decryptor::block_size());
218        C::Encryptor::block_size()
219    }
220
221    fn encrypt(&self, input: &[u8], output: &mut [u8]) {
222        self.new_encryptor().encrypt(input, output);
223    }
224
225    fn encrypt_in_place(&self, inout: &mut [u8]) {
226        self.new_encryptor().encrypt_in_place(inout)
227    }
228
229    fn decrypt(&self, input: &[u8], output: &mut [u8]) {
230        self.new_decryptor().decrypt(input, output)
231    }
232
233    fn decrypt_in_place(&self, inout: &mut [u8]) {
234        self.new_decryptor().decrypt_in_place(inout)
235    }
236}
237
238// Ideally, we'd just use a trait like this in place of Cipher, but the
239// presence of associated types makes it non-dyn-compatible.
240trait PreCipher {
241    type Encryptor: Encryptor;
242    type Decryptor: Decryptor;
243
244    fn set_iv(&mut self, iv: &[u8]);
245    fn reset(&mut self);
246
247    // The minting of new encryptors or decryptors in general should happen
248    // only after set_iv() has been called.
249    fn new_encryptor(&self) -> Self::Encryptor;
250    fn new_decryptor(&self) -> Self::Decryptor;
251}
252
253trait Encryptor {
254    fn block_size() -> usize;
255    fn encrypt(&mut self, input: &[u8], output: &mut [u8]);
256    fn encrypt_in_place(&mut self, inout: &mut [u8]);
257}
258
259trait Decryptor {
260    fn block_size() -> usize;
261    fn decrypt(&mut self, input: &[u8], output: &mut [u8]);
262    fn decrypt_in_place(&mut self, inout: &mut [u8]);
263}
264
265// A general cipher type that requires an initialization vector.
266struct CipherWithIv<E, D>
267where
268    E: Encryptor + KeyIvInit,
269    D: Decryptor + KeyIvInit,
270{
271    key: Vec<u8>,
272    iv: Vec<u8>,
273    phantom: PhantomData<(E, D)>,
274}
275
276impl<E, D> CipherWithIv<E, D>
277where
278    E: Encryptor + KeyIvInit,
279    D: Decryptor + KeyIvInit,
280{
281    fn new(key: &[u8]) -> Self {
282        Self { key: key.to_vec(), iv: Vec::new(), phantom: PhantomData::default() }
283    }
284}
285
286impl<E, D> PreCipher for CipherWithIv<E, D>
287where
288    E: Encryptor + KeyIvInit,
289    D: Decryptor + KeyIvInit,
290{
291    type Encryptor = E;
292    type Decryptor = D;
293
294    fn set_iv(&mut self, iv: &[u8]) {
295        self.iv = iv.to_vec()
296    }
297
298    fn reset(&mut self) {
299        self.iv.clear()
300    }
301
302    fn new_encryptor(&self) -> E {
303        E::new_from_slices(&self.key, &self.iv).unwrap()
304    }
305
306    fn new_decryptor(&self) -> D {
307        D::new_from_slices(&self.key, &self.iv).unwrap()
308    }
309}
310
311// A general cipher type that does not require an initialization vector.
312struct CipherWithoutIv<E, D>
313where
314    E: Encryptor + KeyInit,
315    D: Decryptor + KeyInit,
316{
317    key: Vec<u8>,
318    phantom: PhantomData<(E, D)>,
319}
320
321impl<E, D> CipherWithoutIv<E, D>
322where
323    E: Encryptor + KeyInit,
324    D: Decryptor + KeyInit,
325{
326    fn new(key: &[u8]) -> Self {
327        Self { key: key.to_vec(), phantom: PhantomData::default() }
328    }
329}
330
331impl<E, D> PreCipher for CipherWithoutIv<E, D>
332where
333    E: Encryptor + KeyInit,
334    D: Decryptor + KeyInit,
335{
336    type Encryptor = E;
337    type Decryptor = D;
338
339    // Why not panic? Two reasons:
340    // * the spec does not prescribe any behaviour for calling CipherInit(iv)
341    //   for an algorithm that does require an IV, though it does prescribe
342    //   ignoring any IVs passed to MAC algorithms with MacInit(), so there's
343    //   an argument for consistency;
344    // * it simplifies the one intended callsite of CipherInit() to make
345    //   set_iv() and unconditional call.
346    fn set_iv(&mut self, _iv: &[u8]) {}
347
348    fn reset(&mut self) {}
349
350    fn new_encryptor(&self) -> E {
351        E::new_from_slice(&self.key).unwrap()
352    }
353    fn new_decryptor(&self) -> D {
354        D::new_from_slice(&self.key).unwrap()
355    }
356}
357
358// Provides Encryptor and Decryptor implementations for some of the
359// RustCrypto-shaped encryptors and decryptors (which sadly don't implement
360// some official trait themselves encoding their API).
361//
362// We use token trees in the macro matcher to permit the use of `$encryptor<C>`
363// and `$decryptor<C>`, which wouldn't parse if specified more naturally as
364// type paths.
365macro_rules! rustcrypto_encryptor_and_decryptor {
366    ($encryptor:tt, $decryptor:tt) => {
367        impl<C> Encryptor for $encryptor<C>
368        where
369            C: cipher::BlockCipherEncrypt + cipher::BlockSizeUser,
370            $encryptor<C>: cipher::BlockModeEncrypt,
371        {
372            fn block_size() -> usize {
373                C::block_size()
374            }
375
376            fn encrypt(&mut self, input: &[u8], output: &mut [u8]) {
377                use cipher::BlockModeEncrypt;
378
379                assert!(output.len() >= input.len());
380                let block_size = C::block_size();
381                let chunks =
382                    iter::zip(input.chunks_exact(block_size), output.chunks_exact_mut(block_size));
383                for (in_block, out_block) in chunks {
384                    self.encrypt_block_b2b(
385                        in_block.try_into().unwrap(),
386                        out_block.try_into().unwrap(),
387                    );
388                }
389            }
390
391            fn encrypt_in_place(&mut self, inout: &mut [u8]) {
392                use cipher::BlockModeEncrypt;
393
394                for block in inout.chunks_exact_mut(C::block_size()) {
395                    self.encrypt_block(block.try_into().unwrap())
396                }
397            }
398        }
399
400        impl<C> Decryptor for $decryptor<C>
401        where
402            C: cipher::BlockCipherDecrypt + cipher::BlockSizeUser,
403            $decryptor<C>: cipher::BlockModeDecrypt,
404        {
405            fn block_size() -> usize {
406                C::block_size()
407            }
408
409            fn decrypt(&mut self, input: &[u8], output: &mut [u8]) {
410                use cipher::BlockModeDecrypt;
411
412                assert!(output.len() >= input.len());
413                let block_size = C::block_size();
414                let chunks =
415                    iter::zip(input.chunks_exact(block_size), output.chunks_exact_mut(block_size));
416                for (in_block, out_block) in chunks {
417                    self.decrypt_block_b2b(
418                        in_block.try_into().unwrap(),
419                        out_block.try_into().unwrap(),
420                    );
421                }
422            }
423
424            fn decrypt_in_place(&mut self, inout: &mut [u8]) {
425                use cipher::BlockModeDecrypt;
426
427                for block in inout.chunks_exact_mut(C::block_size()) {
428                    self.decrypt_block(block.try_into().unwrap())
429                }
430            }
431        }
432    };
433}
434
435rustcrypto_encryptor_and_decryptor!(CbcEncryptor, CbcDecryptor);
436rustcrypto_encryptor_and_decryptor!(EcbEncryptor, EcbDecryptor);
437
438type AesCbcNopad<C> = CipherWithIv<cbc::Encryptor<C>, cbc::Decryptor<C>>;
439type Aes128CbcNopad = AesCbcNopad<Aes128>;
440type Aes192CbcNopad = AesCbcNopad<Aes192>;
441type Aes256CbcNopad = AesCbcNopad<Aes256>;
442
443type AesEcbNopad<C> = CipherWithoutIv<ecb::Encryptor<C>, ecb::Decryptor<C>>;
444type Aes128EcbNopad = AesEcbNopad<Aes128>;
445type Aes192EcbNopad = AesEcbNopad<Aes192>;
446type Aes256EcbNopad = AesEcbNopad<Aes256>;
447
448enum CipherType {
449    AesCbcNopad,
450    AesEcbNopad,
451}
452
453trait AsymmetricEncryptionKey {
454    fn decrypt(
455        &self,
456        params: &[Attribute],
457        input: &[u8],
458        output: &mut [u8],
459    ) -> Result<usize, ErrorWithSize>;
460}
461
462trait RsaPadding<D>: RsaPaddingScheme
463where
464    D: 'static + Digest + digest::Digest + Send + Sync,
465{
466    fn new() -> Self;
467}
468
469impl<D> RsaPadding<D> for Oaep
470where
471    D: 'static + Digest + digest::Digest + Send + Sync,
472{
473    fn new() -> Self {
474        Oaep::new::<D>()
475    }
476}
477
478struct RsaEncryptionKey<D, Padding>
479where
480    D: 'static + Digest + digest::Digest + Send + Sync,
481    Padding: RsaPadding<D>,
482{
483    private: Rc<RsaPrivateKey>,
484    phantom: PhantomData<(D, Padding)>,
485}
486
487impl<D, Padding> RsaEncryptionKey<D, Padding>
488where
489    D: 'static + Digest + digest::Digest + Send + Sync,
490    Padding: RsaPadding<D>,
491{
492    fn new(private: Rc<RsaPrivateKey>) -> Self {
493        Self { private, phantom: PhantomData::default() }
494    }
495}
496
497impl<D, Padding> AsymmetricEncryptionKey for RsaEncryptionKey<D, Padding>
498where
499    D: 'static + Digest + digest::Digest + Send + Sync,
500    Padding: RsaPadding<D>,
501{
502    fn decrypt(
503        &self,
504        params: &[Attribute],
505        input: &[u8],
506        output: &mut [u8],
507    ) -> Result<usize, ErrorWithSize> {
508        if !params.is_empty() {
509            unimplemented!();
510        }
511        let output_size = self.private.size() as usize;
512        if input.len() != output_size {
513            return Err(ErrorWithSize::new(Error::BadParameters));
514        }
515        if output.len() < output_size {
516            return Err(ErrorWithSize::short_buffer(output_size));
517        }
518
519        let decrypted = self.private.decrypt(Padding::new(), input).expect("Failed to decrypt");
520        let written = &mut output[..decrypted.len()];
521        written.copy_from_slice(&decrypted);
522        Ok(written.len())
523    }
524}
525
526enum AsymmetricEncryptionKeyType {
527    RsaOaepSha1,
528}
529
530trait AsymmetricSigningKey {
531    fn sign(
532        &self,
533        params: &[Attribute],
534        input: &[u8],
535        output: &mut [u8],
536    ) -> Result<usize, ErrorWithSize>;
537}
538
539trait RsaSignature<D>: RsaSignatureScheme
540where
541    D: 'static + Digest + digest::Digest + Send + Sync,
542{
543    fn new() -> Self;
544}
545
546impl<D> RsaSignature<D> for Pss
547where
548    D: 'static + Digest + digest::Digest + Send + Sync,
549{
550    fn new() -> Self {
551        Pss::new::<D>()
552    }
553}
554
555struct RsaSigningKey<D, Signature>
556where
557    D: 'static + Digest + digest::Digest + Send + Sync,
558    Signature: RsaSignature<D>,
559{
560    private: Rc<RsaPrivateKey>,
561    phantom: PhantomData<(D, Signature)>,
562}
563
564impl<D, Signature> RsaSigningKey<D, Signature>
565where
566    D: 'static + Digest + digest::Digest + Send + Sync,
567    Signature: RsaSignature<D>,
568{
569    fn new(private: Rc<RsaPrivateKey>) -> Self {
570        Self { private, phantom: PhantomData::default() }
571    }
572}
573
574impl<D, Signature> AsymmetricSigningKey for RsaSigningKey<D, Signature>
575where
576    D: 'static + Digest + digest::Digest + Send + Sync,
577    Signature: RsaSignature<D>,
578{
579    fn sign(
580        &self,
581        params: &[Attribute],
582        input: &[u8],
583        output: &mut [u8],
584    ) -> Result<usize, ErrorWithSize> {
585        assert!(params.is_empty());
586        let output_size = self.private.size() as usize;
587        if output.len() < output_size {
588            return Err(ErrorWithSize::short_buffer(output_size));
589        }
590
591        let signed = self
592            .private
593            .sign_with_rng(&mut Rng {}, Signature::new(), input)
594            .expect("Failed to sign");
595        let written = &mut output[..signed.len()];
596        written.copy_from_slice(&signed);
597        Ok(written.len())
598    }
599}
600
601enum AsymmetricSigningKeyType {
602    RsaPssSha1,
603}
604
605// Encapsulated an abstracted helper classes particular to supported
606// algorithms.
607enum Helper {
608    Digest(Box<dyn Digest>),
609    Cipher(Option<Box<dyn Cipher>>, CipherType),
610    Mac(Option<Box<dyn Mac>>, MacType),
611    AsymmetricEncryptionKey(Option<Box<dyn AsymmetricEncryptionKey>>, AsymmetricEncryptionKeyType),
612    AsymmetricSigningKey(Option<Box<dyn AsymmetricSigningKey>>, AsymmetricSigningKeyType),
613}
614
615impl Helper {
616    fn new(algorithm: Algorithm) -> TeeResult<Self> {
617        match algorithm {
618            Algorithm::Sha1 => Ok(Helper::Digest(Box::new(Sha1::default()))),
619            Algorithm::Sha224 => Ok(Helper::Digest(Box::new(Sha224::default()))),
620            Algorithm::Sha256 => Ok(Helper::Digest(Box::new(Sha256::default()))),
621            Algorithm::Sha384 => Ok(Helper::Digest(Box::new(Sha384::default()))),
622            Algorithm::Sha512 => Ok(Helper::Digest(Box::new(Sha512::default()))),
623            Algorithm::AesCbcNopad => Ok(Helper::Cipher(None, CipherType::AesCbcNopad)),
624            Algorithm::AesEcbNopad => Ok(Helper::Cipher(None, CipherType::AesEcbNopad)),
625            Algorithm::AesCmac => Ok(Helper::Mac(None, MacType::AesCmac)),
626            Algorithm::HmacSha1 => Ok(Helper::Mac(None, MacType::HmacSha1)),
627            Algorithm::HmacSha224 => Ok(Helper::Mac(None, MacType::HmacSha224)),
628            Algorithm::HmacSha256 => Ok(Helper::Mac(None, MacType::HmacSha256)),
629            Algorithm::HmacSha384 => Ok(Helper::Mac(None, MacType::HmacSha384)),
630            Algorithm::HmacSha512 => Ok(Helper::Mac(None, MacType::HmacSha512)),
631            Algorithm::RsaesPkcs1OaepMgf1Sha1 => {
632                Ok(Helper::AsymmetricEncryptionKey(None, AsymmetricEncryptionKeyType::RsaOaepSha1))
633            }
634            Algorithm::RsassaPkcs1PssMgf1Sha1 => {
635                Ok(Helper::AsymmetricSigningKey(None, AsymmetricSigningKeyType::RsaPssSha1))
636            }
637            _ => Err(Error::NotSupported),
638        }
639    }
640
641    fn initialize(&mut self, key: &Key) {
642        match self {
643            Helper::Digest(digest) => {
644                // Digests do not need initialization.
645                assert!(matches!(key, Key::Data(NoKey {})));
646                digest.reset()
647            }
648            Helper::Cipher(cipher, cipher_type) => {
649                let Key::Aes(AesKey { secret }) = key else {
650                    panic!("Wrong key type ({:?}) - expected AES", key.get_type());
651                };
652
653                match cipher_type {
654                    CipherType::AesCbcNopad => {
655                        let cbc: Box<dyn Cipher> = match secret.len() {
656                            16 => Box::new(Aes128CbcNopad::new(&secret)),
657                            24 => Box::new(Aes192CbcNopad::new(&secret)),
658                            32 => Box::new(Aes256CbcNopad::new(&secret)),
659                            len => panic!("Invalid AES key length: {len}"),
660                        };
661                        *cipher = Some(cbc);
662                    }
663                    CipherType::AesEcbNopad => {
664                        let ecb: Box<dyn Cipher> = match secret.len() {
665                            16 => Box::new(Aes128EcbNopad::new(&secret)),
666                            24 => Box::new(Aes192EcbNopad::new(&secret)),
667                            32 => Box::new(Aes256EcbNopad::new(&secret)),
668                            len => panic!("Invalid AES key length: {len}"),
669                        };
670                        *cipher = Some(ecb);
671                    }
672                }
673            }
674            Helper::Mac(mac, mac_type) => match mac_type {
675                MacType::AesCmac => {
676                    let Key::Aes(AesKey { secret }) = key else {
677                        panic!("Wrong key type ({:?}) - expected AES", key.get_type());
678                    };
679                    let cmac: Box<dyn Mac> = match secret.len() {
680                        16 => Box::new(AesCmac128::new_from_slice(&secret).unwrap()),
681                        24 => Box::new(AesCmac192::new_from_slice(&secret).unwrap()),
682                        32 => Box::new(AesCmac256::new_from_slice(&secret).unwrap()),
683                        len => panic!("Invalid AES key length: {len}"),
684                    };
685                    *mac = Some(cmac);
686                }
687                MacType::HmacSha1 => {
688                    let Key::HmacSha1(HmacSha1Key { secret }) = key else {
689                        panic!("Wrong key type ({:?}) - expected HMAC SHA1", key.get_type());
690                    };
691                    *mac = Some(Box::new(
692                        <HmacSha1 as sha1::digest::KeyInit>::new_from_slice(&secret).unwrap(),
693                    ))
694                }
695                MacType::HmacSha224 => {
696                    let Key::HmacSha224(HmacSha224Key { secret }) = key else {
697                        panic!("Wrong key type ({:?}) - expected HMAC SHA224", key.get_type());
698                    };
699                    *mac = Some(Box::new(
700                        <HmacSha224 as sha1::digest::KeyInit>::new_from_slice(&secret).unwrap(),
701                    ))
702                }
703                MacType::HmacSha256 => {
704                    let Key::HmacSha256(HmacSha256Key { secret }) = key else {
705                        panic!("Wrong key type ({:?}) - expected HMAC SHA256", key.get_type());
706                    };
707                    *mac = Some(Box::new(
708                        <HmacSha256 as sha1::digest::KeyInit>::new_from_slice(&secret).unwrap(),
709                    ))
710                }
711                MacType::HmacSha384 => {
712                    let Key::HmacSha384(HmacSha384Key { secret }) = key else {
713                        panic!("Wrong key type ({:?}) - expected HMAC SHA384", key.get_type());
714                    };
715                    *mac = Some(Box::new(
716                        <HmacSha384 as sha1::digest::KeyInit>::new_from_slice(&secret).unwrap(),
717                    ))
718                }
719                MacType::HmacSha512 => {
720                    let Key::HmacSha512(HmacSha512Key { secret }) = key else {
721                        panic!("Wrong key type ({:?}) - expected HMAC SHA512", key.get_type());
722                    };
723                    *mac = Some(Box::new(
724                        <HmacSha512 as sha1::digest::KeyInit>::new_from_slice(&secret).unwrap(),
725                    ))
726                }
727            },
728            Helper::AsymmetricEncryptionKey(aenc, aenc_type) => match aenc_type {
729                AsymmetricEncryptionKeyType::RsaOaepSha1 => {
730                    let Key::RsaKeypair(rsa) = key else {
731                        panic!("Wrong key type ({:?}) - expected RSA keypair", key.get_type());
732                    };
733                    *aenc = Some(Box::new(RsaEncryptionKey::<Sha1, Oaep>::new(rsa.private_key())));
734                }
735            },
736            Helper::AsymmetricSigningKey(asign, asign_type) => match asign_type {
737                AsymmetricSigningKeyType::RsaPssSha1 => {
738                    let Key::RsaKeypair(rsa) = key else {
739                        panic!("Wrong key type ({:?}) - expected RSA keypair", key.get_type());
740                    };
741                    *asign = Some(Box::new(RsaSigningKey::<Sha1, Pss>::new(rsa.private_key())));
742                }
743            },
744        }
745    }
746
747    fn reset(&mut self) {
748        match self {
749            Helper::Digest(digest) => digest.reset(),
750            Helper::Cipher(cipher, _) => {
751                if let Some(cipher) = cipher {
752                    cipher.reset()
753                }
754            }
755            Helper::Mac(mac, _) => {
756                if let Some(mac) = mac {
757                    mac.reset()
758                }
759            }
760            Helper::AsymmetricEncryptionKey(_, _) => {}
761            Helper::AsymmetricSigningKey(_, _) => {}
762        }
763    }
764}
765
766#[derive(Debug, Eq, PartialEq)]
767enum OpState {
768    Initial,
769    Active,
770    // Holds the finalized data yet to be fully extracted, along with an index
771    // pointing to the next byte to extract.
772    Extracting((Vec<u8>, usize)),
773}
774
775pub struct Operation {
776    algorithm: Algorithm,
777    mode: Mode,
778    key: Key,
779    max_key_size: u32, // The initial, allocated max key size.
780    state: OpState,
781    helper: Helper,
782}
783
784impl Operation {
785    fn new(algorithm: Algorithm, mode: Mode, max_key_size: u32) -> TeeResult<Self> {
786        Ok(Self {
787            algorithm,
788            mode,
789            key: Key::Data(NoKey {}),
790            max_key_size,
791            state: OpState::Initial,
792            helper: Helper::new(algorithm)?,
793        })
794    }
795
796    fn as_digest(&mut self) -> &mut Box<dyn Digest> {
797        if let Helper::Digest(digest) = &mut self.helper {
798            digest
799        } else {
800            panic!("{:?} is not a digest algorithm", self.algorithm)
801        }
802    }
803
804    fn as_cipher(&mut self) -> &mut Box<dyn Cipher> {
805        if let Helper::Cipher(cipher, _) = &mut self.helper {
806            cipher.as_mut().expect("TEE_OperationSetKey() has not yet been called")
807        } else {
808            panic!("{:?} is not a cipher algorithm", self.algorithm)
809        }
810    }
811
812    fn as_mac(&mut self) -> &mut Box<dyn Mac> {
813        if let Helper::Mac(mac, _) = &mut self.helper {
814            mac.as_mut().expect("TEE_OperationSetKey() has not yet been called")
815        } else {
816            panic!("{:?} is not a MAC algorithm", self.algorithm)
817        }
818    }
819
820    fn as_asymmetric_encryption_key(&mut self) -> &mut Box<dyn AsymmetricEncryptionKey> {
821        if let Helper::AsymmetricEncryptionKey(aenc, _) = &mut self.helper {
822            aenc.as_mut().expect("TEE_OperationSetKey() has not yet been called")
823        } else {
824            panic!("{:?} is not a asymmetric encryption key algorithm", self.algorithm)
825        }
826    }
827
828    fn as_asymmetric_signing_key(&mut self) -> &mut Box<dyn AsymmetricSigningKey> {
829        if let Helper::AsymmetricSigningKey(aenc, _) = &mut self.helper {
830            aenc.as_mut().expect("TEE_OperationSetKey() has not yet been called")
831        } else {
832            panic!("{:?} is not a asymmetric signing key algorithm", self.algorithm)
833        }
834    }
835
836    // Returns whether the operation is in the extracting state and, if so, the
837    // number of remaining bytes left to extract.
838    fn is_extracting(&self) -> (bool, usize) {
839        if let OpState::Extracting((ref data, ref pos)) = self.state {
840            (true, data.len() - pos)
841        } else {
842            (false, 0)
843        }
844    }
845
846    fn reset(&mut self) {
847        self.helper.reset();
848        self.state = OpState::Initial;
849    }
850
851    fn set_key(&mut self, obj: Rc<RefCell<dyn Object>>) -> TeeResult {
852        let obj = obj.borrow();
853        let key = obj.key();
854
855        assert!(
856            key.max_size() <= self.max_key_size,
857            "Provided key size ({}) exceeds configured max ({})",
858            key.max_size(),
859            self.max_key_size
860        );
861
862        assert_eq!(
863            self.state,
864            OpState::Initial,
865            "Operation must be in the initial state (not {:?})",
866            self.state
867        );
868
869        match self.algorithm {
870            Algorithm::AesCbcNopad | Algorithm::AesEcbNopad => match self.mode {
871                Mode::Encrypt | Mode::Decrypt => {
872                    let usage = obj.usage();
873                    if self.mode == Mode::Encrypt {
874                        assert!(usage.contains(Usage::ENCRYPT | Usage::VERIFY));
875                    } else {
876                        assert!(usage.contains(Usage::DECRYPT | Usage::SIGN));
877                    }
878                }
879                _ => return Err(Error::NotImplemented),
880            },
881            Algorithm::Md5
882            | Algorithm::Sha1
883            | Algorithm::Sha224
884            | Algorithm::Sha256
885            | Algorithm::Sha384
886            | Algorithm::Sha512
887            | Algorithm::Sha3_224
888            | Algorithm::Sha3_256
889            | Algorithm::Sha3_384
890            | Algorithm::Sha3_512
891            | Algorithm::Shake128
892            | Algorithm::Shake256 => {
893                panic!("Algorithm {:?} has no associated object type", self.algorithm);
894            }
895            Algorithm::AesCmac
896            | Algorithm::HmacSha1
897            | Algorithm::HmacSha224
898            | Algorithm::HmacSha256
899            | Algorithm::HmacSha384
900            | Algorithm::HmacSha512 => {}
901            Algorithm::RsaesPkcs1OaepMgf1Sha1 => {}
902            Algorithm::RsassaPkcs1PssMgf1Sha1 => {}
903            _ => return Err(Error::NotImplemented),
904        };
905        self.key = key.clone();
906        self.helper.initialize(&self.key);
907        Ok(())
908    }
909
910    fn clear_key(&mut self) -> TeeResult {
911        self.key = Key::Data(NoKey {});
912        self.state = OpState::Initial;
913        Ok(())
914    }
915
916    // Provided the operation is in its extracting state, this reads as many
917    // bytes of that data as possible into the provided buffer, returning the
918    // size of the read.
919    fn extract_finalized(&mut self, buf: &mut [u8]) -> usize {
920        let OpState::Extracting((ref data, ref mut pos)) = self.state else {
921            panic!("Operation is not in the extracting state: {:?}", self.state);
922        };
923        if buf.is_empty() || *pos >= data.len() {
924            return 0;
925        }
926        let read_size = min(data.len() - *pos, buf.len());
927        let in_chunk = &data.as_slice()[*pos..(*pos + read_size)];
928        let out_chunk = &mut buf[..read_size];
929        out_chunk.copy_from_slice(in_chunk);
930        *pos += read_size;
931        read_size
932    }
933
934    // See TEE_DigestUpdate().
935    fn update_digest(&mut self, chunk: &[u8]) {
936        assert_eq!(self.mode, Mode::Digest);
937        assert!(self.state == OpState::Initial || self.state == OpState::Active);
938        self.as_digest().update(chunk);
939        self.state = OpState::Active;
940    }
941
942    // See TEE_DigestDoFinal().
943    //
944    // This should be two separate operations each with clean semantics:
945    // update + finalize. However, the spec wants the two zipped together here
946    // where the first can't happen if the preconditions of the second aren't
947    // met, adding complication.
948    fn update_and_finalize_digest_into(
949        &mut self,
950        last_chunk: &[u8],
951        buf: &mut [u8],
952    ) -> Result<(), ErrorWithSize> {
953        assert_eq!(self.mode, Mode::Digest);
954
955        if let (true, left_to_extract) = self.is_extracting() {
956            assert!(last_chunk.is_empty());
957
958            if left_to_extract > buf.len() {
959                return Err(ErrorWithSize::short_buffer(left_to_extract));
960            }
961
962            let written = self.extract_digest(buf);
963            debug_assert_eq!(written, left_to_extract);
964            self.state = OpState::Initial;
965            return Ok(());
966        }
967
968        let buf = {
969            let digest = self.as_digest();
970            let output_size = digest.output_size();
971            if output_size > buf.len() {
972                return Err(ErrorWithSize::short_buffer(output_size));
973            }
974
975            if !last_chunk.is_empty() {
976                digest.update(last_chunk);
977            }
978            &mut buf[..output_size]
979        };
980
981        self.as_digest().finalize_into_reset(buf).unwrap();
982        self.state = OpState::Initial;
983        Ok(())
984    }
985
986    // Finalizes the digest and puts the operation in the extracting state. If
987    // already in the extracting state, this is a no-op.
988    fn finalize_digest(&mut self) {
989        assert_eq!(self.mode, Mode::Digest);
990        let (extracting, _) = self.is_extracting();
991        if extracting {
992            return;
993        }
994
995        let bytes = self.as_digest().finalize_reset();
996        self.state = OpState::Extracting((Vec::from(bytes), 0));
997    }
998
999    // See TEE_DigestExtract().
1000    fn extract_digest(&mut self, buf: &mut [u8]) -> usize {
1001        self.finalize_digest();
1002        self.extract_finalized(buf)
1003    }
1004
1005    // See TEE_CipherInit()
1006    fn init_cipher(&mut self, iv: &[u8]) {
1007        if self.state == OpState::Active {
1008            self.as_cipher().reset();
1009        } else {
1010            assert_eq!(self.state, OpState::Initial);
1011        }
1012
1013        self.as_cipher().set_iv(iv);
1014
1015        // Currently supported MAC algorithms don't deal in initialization vectors.
1016        self.state = OpState::Active;
1017    }
1018
1019    // The error value indicates the minimum required size of the output buffer
1020    // (i.e., the total number of full blocks to encrypt/decrypt).
1021    fn update_cipher(&mut self, src: &[u8], dest: &mut [u8]) -> Result<(), ErrorWithSize> {
1022        assert_eq!(self.state, OpState::Active);
1023
1024        let block_size = self.as_cipher().block_size();
1025        let num_blocks_in = src.len() / block_size;
1026        let num_blocks_out = dest.len() / block_size;
1027
1028        // The output buffer size should be at least the total size of the
1029        // number of full blocks in `src` to encrypt/decrypt.
1030        if num_blocks_in > num_blocks_out {
1031            return Err(ErrorWithSize::short_buffer(num_blocks_in * block_size));
1032        }
1033
1034        if self.mode == Mode::Encrypt {
1035            self.as_cipher().encrypt(src, dest);
1036        } else {
1037            assert_eq!(self.mode, Mode::Decrypt);
1038            self.as_cipher().decrypt(src, dest);
1039        }
1040        Ok(())
1041    }
1042
1043    fn update_cipher_in_place(&mut self, inout: &mut [u8]) {
1044        assert_eq!(self.state, OpState::Active);
1045
1046        if self.mode == Mode::Encrypt {
1047            self.as_cipher().encrypt_in_place(inout);
1048        } else {
1049            assert_eq!(self.mode, Mode::Decrypt);
1050            self.as_cipher().decrypt_in_place(inout);
1051        }
1052    }
1053
1054    // The error value indicates the minimum required size of the output buffer
1055    // (i.e., the total number of full blocks to encrypt/decrypt, which should
1056    // be the same size as `src` itself).
1057    fn finalize_cipher(&mut self, src: &[u8], dest: &mut [u8]) -> Result<(), ErrorWithSize> {
1058        let block_size = self.as_cipher().block_size();
1059        assert_eq!(src.len() % block_size, 0);
1060        assert!(dest.len() >= src.len());
1061        self.update_cipher(src, dest)?;
1062        self.state = OpState::Initial;
1063        Ok(())
1064    }
1065
1066    fn finalize_cipher_in_place(&mut self, inout: &mut [u8]) {
1067        let block_size = self.as_cipher().block_size();
1068        assert_eq!(inout.len() % block_size, 0);
1069        self.update_cipher_in_place(inout);
1070        self.state = OpState::Initial;
1071    }
1072
1073    // See TEE_MACInit().
1074    fn init_mac(&mut self, _iv: &[u8]) {
1075        assert_eq!(self.mode, Mode::Mac);
1076        assert!(self.state == OpState::Initial || self.state == OpState::Active);
1077
1078        if self.state == OpState::Active {
1079            self.as_mac().reset();
1080        }
1081
1082        // Currently supported MAC algorithms don't deal in initialization
1083        // vectors; the spec say to ignore the provided one in that case.
1084
1085        self.state = OpState::Active;
1086    }
1087
1088    // See TEE_MACUpdate().
1089    fn update_mac(&mut self, chunk: &[u8]) {
1090        assert_eq!(self.mode, Mode::Mac);
1091        assert_eq!(self.state, OpState::Active);
1092
1093        let mac = self.as_mac();
1094        if !chunk.is_empty() {
1095            mac.update(chunk);
1096        }
1097    }
1098
1099    // See TEE_MACComputeFinal().
1100    fn compute_final_mac(
1101        &mut self,
1102        message: &[u8],
1103        output: &mut [u8],
1104    ) -> Result<(), ErrorWithSize> {
1105        assert_eq!(self.mode, Mode::Mac);
1106        assert_eq!(self.state, OpState::Active);
1107
1108        let output_size = self.as_mac().output_size();
1109        if output.len() < output_size {
1110            return Err(ErrorWithSize::short_buffer(output_size));
1111        }
1112
1113        // Make sure we validate the output buffer size before updating the
1114        // digest.
1115        let mac = self.as_mac();
1116        if !message.is_empty() {
1117            mac.update(message);
1118        }
1119        mac.finalize_into_reset(&mut output[..output_size]);
1120        self.state = OpState::Initial;
1121        Ok(())
1122    }
1123
1124    // See TEE_MACCompareFinal().
1125    fn compare_final_mac(&mut self, message: &[u8], expected: &[u8]) -> TeeResult {
1126        self.update_mac(message);
1127        let result = self.as_mac().verify_reset(expected);
1128        self.state = OpState::Initial;
1129        result
1130    }
1131
1132    // See TEE_AsymmetricDecrypt().
1133    fn asymmetric_decrypt(
1134        &mut self,
1135        params: &[Attribute],
1136        src: &[u8],
1137        dest: &mut [u8],
1138    ) -> Result<usize, ErrorWithSize> {
1139        assert_eq!(self.mode, Mode::Decrypt);
1140        self.as_asymmetric_encryption_key().decrypt(params, src, dest)
1141    }
1142
1143    // See TEE_AsymmetricSignDigest().
1144    fn asymmetric_sign_digest(
1145        &mut self,
1146        params: &[Attribute],
1147        digest: &[u8],
1148        signature: &mut [u8],
1149    ) -> Result<usize, ErrorWithSize> {
1150        assert_eq!(self.mode, Mode::Sign);
1151        self.as_asymmetric_signing_key().sign(params, digest, signature)
1152    }
1153}
1154
1155pub struct Operations {
1156    operations: HashMap<OperationHandle, RefCell<Operation>>,
1157    next_operation_handle_value: OperationHandle,
1158}
1159
1160impl Operations {
1161    pub fn new() -> Self {
1162        Self {
1163            operations: HashMap::new(),
1164            next_operation_handle_value: OperationHandle::from_value(1),
1165        }
1166    }
1167
1168    pub fn allocate(
1169        &mut self,
1170        algorithm: Algorithm,
1171        mode: Mode,
1172        max_key_size: u32,
1173    ) -> TeeResult<OperationHandle> {
1174        // We could directly check `FooKey::is_valid_size(max_key_size)` in
1175        // each match arm, but by forwarding the appropriate key size check
1176        // function pointer and doing it indirectly after the match statement,
1177        // we ensure that the check is always made and reduce a bit of
1178        // boilerplate while we're at it.
1179        let is_valid_key_size = match algorithm {
1180            Algorithm::AesCbcNopad | Algorithm::AesEcbNopad => {
1181                match mode {
1182                    Mode::Encrypt | Mode::Decrypt => {}
1183                    _ => {
1184                        return Err(Error::NotSupported);
1185                    }
1186                };
1187                AesKey::is_valid_size
1188            }
1189            Algorithm::Md5
1190            | Algorithm::Sha1
1191            | Algorithm::Sha224
1192            | Algorithm::Sha256
1193            | Algorithm::Sha384
1194            | Algorithm::Sha512
1195            | Algorithm::Sha3_224
1196            | Algorithm::Sha3_256
1197            | Algorithm::Sha3_384
1198            | Algorithm::Sha3_512
1199            | Algorithm::Shake128
1200            | Algorithm::Shake256 => {
1201                if mode != Mode::Digest {
1202                    return Err(Error::NotSupported);
1203                }
1204                NoKey::is_valid_size
1205            }
1206            Algorithm::AesCmac => {
1207                if mode != Mode::Mac {
1208                    return Err(Error::NotSupported);
1209                }
1210                AesKey::is_valid_size
1211            }
1212            Algorithm::HmacSha1 => {
1213                if mode != Mode::Mac {
1214                    return Err(Error::NotSupported);
1215                }
1216                HmacSha1Key::is_valid_size
1217            }
1218            Algorithm::HmacSha224 => {
1219                if mode != Mode::Mac {
1220                    return Err(Error::NotSupported);
1221                }
1222                HmacSha224Key::is_valid_size
1223            }
1224            Algorithm::HmacSha256 => {
1225                if mode != Mode::Mac {
1226                    return Err(Error::NotSupported);
1227                }
1228                HmacSha256Key::is_valid_size
1229            }
1230            Algorithm::HmacSha384 => {
1231                if mode != Mode::Mac {
1232                    return Err(Error::NotSupported);
1233                }
1234                HmacSha384Key::is_valid_size
1235            }
1236            Algorithm::HmacSha512 => {
1237                if mode != Mode::Mac {
1238                    return Err(Error::NotSupported);
1239                }
1240                HmacSha512Key::is_valid_size
1241            }
1242            Algorithm::RsaesPkcs1OaepMgf1Sha1 => {
1243                if mode != Mode::Encrypt && mode != Mode::Decrypt {
1244                    return Err(Error::NotSupported);
1245                }
1246                RsaKeypair::is_valid_size
1247            }
1248            Algorithm::RsassaPkcs1PssMgf1Sha1 => {
1249                if mode != Mode::Sign && mode != Mode::Verify {
1250                    return Err(Error::NotSupported);
1251                }
1252                RsaKeypair::is_valid_size
1253            }
1254            _ => {
1255                inspect_stubs::track_stub!(
1256                    TODO("https://fxbug.dev/360942581"),
1257                    "unsupported algorithm",
1258                );
1259                return Err(Error::NotImplemented);
1260            }
1261        };
1262        if !is_valid_key_size(max_key_size) {
1263            return Err(Error::NotSupported);
1264        }
1265        let operation = Operation::new(algorithm, mode, max_key_size)?;
1266        let handle = self.allocate_operation_handle();
1267        let prev = self.operations.insert(handle, RefCell::new(operation));
1268        debug_assert!(prev.is_none());
1269        Ok(handle)
1270    }
1271
1272    fn allocate_operation_handle(&mut self) -> OperationHandle {
1273        let handle = self.next_operation_handle_value;
1274        self.next_operation_handle_value = OperationHandle::from_value(*handle + 1);
1275        handle
1276    }
1277
1278    fn get_mut(&self, operation: OperationHandle) -> RefMut<'_, Operation> {
1279        self.operations.get(&operation).unwrap().borrow_mut()
1280    }
1281
1282    pub fn free(&mut self, operation: OperationHandle) {
1283        if operation.is_null() {
1284            return;
1285        }
1286        let _ = self.operations.remove(&operation).unwrap();
1287    }
1288
1289    pub fn reset(&mut self, operation: OperationHandle) {
1290        self.get_mut(operation).reset()
1291    }
1292
1293    pub fn set_key(
1294        &mut self,
1295        operation: OperationHandle,
1296        key: Rc<RefCell<dyn Object>>,
1297    ) -> TeeResult {
1298        self.get_mut(operation).set_key(key)
1299    }
1300
1301    pub fn clear_key(&mut self, operation: OperationHandle) -> TeeResult {
1302        self.get_mut(operation).clear_key()
1303    }
1304
1305    pub fn update_digest(&mut self, operation: OperationHandle, chunk: &[u8]) {
1306        self.get_mut(operation).update_digest(chunk);
1307    }
1308
1309    pub fn update_and_finalize_digest_into(
1310        &mut self,
1311        operation: OperationHandle,
1312        last_chunk: &[u8],
1313        buf: &mut [u8],
1314    ) -> Result<(), ErrorWithSize> {
1315        self.get_mut(operation).update_and_finalize_digest_into(last_chunk, buf)
1316    }
1317
1318    pub fn extract_digest<'a>(&mut self, operation: OperationHandle, buf: &'a mut [u8]) -> usize {
1319        self.get_mut(operation).extract_digest(buf)
1320    }
1321
1322    pub fn init_cipher(&mut self, operation: OperationHandle, iv: &[u8]) {
1323        self.get_mut(operation).init_cipher(iv)
1324    }
1325
1326    pub fn update_cipher(
1327        &mut self,
1328        operation: OperationHandle,
1329        input: &[u8],
1330        output: &mut [u8],
1331    ) -> Result<(), ErrorWithSize> {
1332        self.get_mut(operation).update_cipher(input, output)
1333    }
1334
1335    pub fn update_cipher_in_place(&mut self, operation: OperationHandle, inout: &mut [u8]) {
1336        self.get_mut(operation).update_cipher_in_place(inout)
1337    }
1338
1339    pub fn finalize_cipher(
1340        &mut self,
1341        operation: OperationHandle,
1342        input: &[u8],
1343        output: &mut [u8],
1344    ) -> Result<(), ErrorWithSize> {
1345        self.get_mut(operation).finalize_cipher(input, output)
1346    }
1347
1348    pub fn finalize_cipher_in_place(&mut self, operation: OperationHandle, inout: &mut [u8]) {
1349        self.get_mut(operation).finalize_cipher_in_place(inout)
1350    }
1351
1352    pub fn init_mac(&mut self, operation: OperationHandle, iv: &[u8]) {
1353        self.get_mut(operation).init_mac(iv)
1354    }
1355
1356    pub fn update_mac(&mut self, operation: OperationHandle, chunk: &[u8]) {
1357        self.get_mut(operation).update_mac(chunk)
1358    }
1359
1360    pub fn compute_final_mac(
1361        &mut self,
1362        operation: OperationHandle,
1363        message: &[u8],
1364        mac: &mut [u8],
1365    ) -> Result<(), ErrorWithSize> {
1366        self.get_mut(operation).compute_final_mac(message, mac)
1367    }
1368
1369    pub fn compare_final_mac(
1370        &mut self,
1371        operation: OperationHandle,
1372        message: &[u8],
1373        mac: &[u8],
1374    ) -> TeeResult {
1375        self.get_mut(operation).compare_final_mac(message, mac)
1376    }
1377
1378    pub fn asymmetric_decrypt(
1379        &mut self,
1380        operation: OperationHandle,
1381        params: &[Attribute],
1382        src: &[u8],
1383        dest: &mut [u8],
1384    ) -> Result<usize, ErrorWithSize> {
1385        self.get_mut(operation).asymmetric_decrypt(params, src, dest)
1386    }
1387
1388    pub fn asymmetric_sign_digest(
1389        &mut self,
1390        operation: OperationHandle,
1391        params: &[Attribute],
1392        digest: &[u8],
1393        signature: &mut [u8],
1394    ) -> Result<usize, ErrorWithSize> {
1395        self.get_mut(operation).asymmetric_sign_digest(params, digest, signature)
1396    }
1397}
1398
1399#[cfg(test)]
1400mod tests {
1401    use super::*;
1402
1403    #[fuchsia::test]
1404    fn operation_lifecycle() -> Result<(), Error> {
1405        let mut operations = Operations::new();
1406
1407        let operation = operations.allocate(Algorithm::Sha256, Mode::Digest, 0).unwrap();
1408
1409        operations.free(operation);
1410
1411        Ok(())
1412    }
1413}