opentitanlib/crypto/
spx.rs

1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5use anyhow::{Context, Result, anyhow, ensure};
6use serde::{Deserialize, Serialize};
7use serde_annotate::Annotate;
8use std::io::{Read, Write};
9use std::str::FromStr;
10
11use super::Error;
12use sphincsplus::{DecodeKey, SpxPublicKey};
13
14#[derive(Debug, Serialize, Deserialize, Annotate)]
15pub struct SpxRawPublicKey {
16    #[serde(with = "serde_bytes")]
17    #[annotate(format = hexstr)]
18    pub key: Vec<u8>,
19}
20
21impl Default for SpxRawPublicKey {
22    fn default() -> Self {
23        Self { key: vec![0; 32] }
24    }
25}
26
27impl TryFrom<&sphincsplus::SpxPublicKey> for SpxRawPublicKey {
28    type Error = Error;
29    fn try_from(v: &SpxPublicKey) -> Result<Self, Self::Error> {
30        Ok(Self {
31            key: v.as_bytes().to_vec(),
32        })
33    }
34}
35
36impl FromStr for SpxRawPublicKey {
37    type Err = Error;
38    fn from_str(s: &str) -> Result<Self, Self::Err> {
39        let key = SpxPublicKey::read_pem_file(s)
40            .with_context(|| format!("Failed to load {s}"))
41            .map_err(Error::Other)?;
42        SpxRawPublicKey::try_from(&key)
43    }
44}
45
46impl SpxRawPublicKey {
47    pub const SIZE: usize = 32;
48    pub fn read(src: &mut impl Read) -> Result<Self> {
49        let mut key = Self::default();
50        key.key.resize(32, 0);
51        src.read_exact(&mut key.key)?;
52        Ok(key)
53    }
54    pub fn write(&self, dest: &mut impl Write) -> Result<()> {
55        ensure!(
56            self.key.len() == Self::SIZE,
57            Error::InvalidPublicKey(anyhow!("bad key length: {}", self.key.len()))
58        );
59        dest.write_all(&self.key)?;
60        Ok(())
61    }
62}