1 // Copyright 2023, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 //! Handles the construction of the MACed public key.
16
17 use alloc::vec::Vec;
18 use bssl_avf::hmac_sha256;
19 use core::result;
20 use coset::{iana, CborSerializable, CoseKey, CoseMac0, CoseMac0Builder, HeaderBuilder};
21 use service_vm_comm::RequestProcessingError;
22
23 type Result<T> = result::Result<T, RequestProcessingError>;
24
25 /// Verifies the MAC of the given public key.
validate_public_key(maced_public_key: &[u8], hmac_key: &[u8]) -> Result<CoseKey>26 pub fn validate_public_key(maced_public_key: &[u8], hmac_key: &[u8]) -> Result<CoseKey> {
27 let cose_mac = CoseMac0::from_slice(maced_public_key)?;
28 cose_mac.verify_tag(&[], |tag, data| verify_tag(tag, data, hmac_key))?;
29 let payload = cose_mac.payload.ok_or(RequestProcessingError::KeyToSignHasEmptyPayload)?;
30 Ok(CoseKey::from_slice(&payload)?)
31 }
32
verify_tag(tag: &[u8], data: &[u8], hmac_key: &[u8]) -> Result<()>33 fn verify_tag(tag: &[u8], data: &[u8], hmac_key: &[u8]) -> Result<()> {
34 let computed_tag = hmac_sha256(hmac_key, data)?;
35 if tag == computed_tag {
36 Ok(())
37 } else {
38 Err(RequestProcessingError::InvalidMac)
39 }
40 }
41
42 /// Returns the MACed public key.
build_maced_public_key(public_key: CoseKey, hmac_key: &[u8]) -> Result<Vec<u8>>43 pub fn build_maced_public_key(public_key: CoseKey, hmac_key: &[u8]) -> Result<Vec<u8>> {
44 const ALGO: iana::Algorithm = iana::Algorithm::HMAC_256_256;
45
46 let external_aad = &[];
47 let protected = HeaderBuilder::new().algorithm(ALGO).build();
48 let cose_mac = CoseMac0Builder::new()
49 .protected(protected)
50 .payload(public_key.to_vec()?)
51 .try_create_tag(external_aad, |data| hmac_sha256(hmac_key, data).map(|v| v.to_vec()))?
52 .build();
53 Ok(cose_mac.to_vec()?)
54 }
55