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