blob: b35275f599fcb5197fa0b49722dd546b22b7eb64 [file] [log] [blame]
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Various representations of salts for extended advertisements.
use nom::combinator;
use crypto_provider::{aes::ctr::AesCtrNonce, CryptoProvider, CryptoRng, FromCryptoRng};
use np_hkdf::v1_salt::ExtendedV1Salt;
use crate::helpers::parse_byte_array;
/// Common behavior for V1 section salts.
pub trait V1Salt: Copy + Into<MultiSalt> {
/// Derive the nonce used for section encryption.
///
/// Both kinds of salts can compute the nonce needed for de/encrypting a
/// section, but only extended salts can have data derived from them.
fn compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce;
}
impl V1Salt for ExtendedV1Salt {
fn compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce {
self.derive::<12, C>(None).expect("AES-CTR nonce is a valid HKDF size")
}
}
pub(crate) const SHORT_SALT_LEN: usize = 2;
/// A byte buffer the size of a V1 short salt
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct ShortV1Salt([u8; SHORT_SALT_LEN]);
impl From<[u8; SHORT_SALT_LEN]> for ShortV1Salt {
fn from(value: [u8; SHORT_SALT_LEN]) -> Self {
Self(value)
}
}
impl ShortV1Salt {
pub(crate) fn bytes(&self) -> &[u8; SHORT_SALT_LEN] {
&self.0
}
pub(crate) fn parse(input: &[u8]) -> nom::IResult<&[u8], Self> {
combinator::map(parse_byte_array::<SHORT_SALT_LEN>, Self)(input)
}
}
impl V1Salt for ShortV1Salt {
fn compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce {
np_hkdf::extended_mic_section_short_salt_nonce::<C>(self.0)
}
}
impl FromCryptoRng for ShortV1Salt {
fn new_random<R: CryptoRng>(rng: &mut R) -> Self {
rng.gen::<[u8; SHORT_SALT_LEN]>().into()
}
}
/// Either a short or extended salt.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum MultiSalt {
/// A 2-byte salt
Short(ShortV1Salt),
/// A 16-byte salt
Extended(ExtendedV1Salt),
}
impl MultiSalt {
/// Salt bytes as a slice, for when variable-size access is sensible
pub fn as_slice(&self) -> &[u8] {
match self {
MultiSalt::Short(s) => s.bytes().as_slice(),
MultiSalt::Extended(s) => s.bytes().as_slice(),
}
}
}
impl From<ExtendedV1Salt> for MultiSalt {
fn from(value: ExtendedV1Salt) -> Self {
Self::Extended(value)
}
}
impl From<ShortV1Salt> for MultiSalt {
fn from(value: ShortV1Salt) -> Self {
Self::Short(value)
}
}
impl V1Salt for MultiSalt {
/// Both kinds of salts can compute the nonce needed for decrypting an
/// advertisement, but only extended salts can have data derived from them.
fn compute_nonce<C: CryptoProvider>(&self) -> AesCtrNonce {
match self {
Self::Short(s) => V1Salt::compute_nonce::<C>(s),
Self::Extended(s) => s.compute_nonce::<C>(),
}
}
}