|
| 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 | + |
| 5 | +use pem_rfc7468::Decoder; |
| 6 | +use std::fs::File; |
| 7 | +use std::io::Read; |
| 8 | +use std::path::Path; |
| 9 | + |
| 10 | +use crate::{SphincsPlus, SpxError}; |
| 11 | +use util::clean_pem_bytes_for_parsing; |
| 12 | + |
| 13 | +#[derive(Clone, PartialEq, Eq, Debug)] |
| 14 | +pub struct SpxRawSignature { |
| 15 | + raw_data: Vec<u8>, |
| 16 | +} |
| 17 | + |
| 18 | +impl SpxRawSignature { |
| 19 | + pub fn read(src: &mut impl Read, algorithm: SphincsPlus) -> Result<Self, SpxError> { |
| 20 | + let mut raw_data = Vec::new(); |
| 21 | + raw_data.resize(algorithm.signature_len(), 0); |
| 22 | + src.read_exact(&mut raw_data)?; |
| 23 | + Ok(SpxRawSignature { raw_data }) |
| 24 | + } |
| 25 | + |
| 26 | + pub fn read_from_file(path: &Path, algorithm: SphincsPlus) -> Result<Self, SpxError> { |
| 27 | + let mut file = File::open(path)?; |
| 28 | + let file_size = std::fs::metadata(path)?.len() as usize; |
| 29 | + |
| 30 | + if file_size == algorithm.signature_len() { |
| 31 | + // This must be a raw signature, just read it as is. |
| 32 | + SpxRawSignature::read(&mut file, algorithm) |
| 33 | + } else { |
| 34 | + let mut data = Vec::<u8>::new(); |
| 35 | + |
| 36 | + file.read_to_end(&mut data)?; |
| 37 | + |
| 38 | + // Try parsing as PEM decoding. |
| 39 | + SpxRawSignature::from_pem(&data, algorithm) |
| 40 | + } |
| 41 | + } |
| 42 | + |
| 43 | + fn from_pem(data: &[u8], algorithm: SphincsPlus) -> Result<Self, SpxError> { |
| 44 | + // Ensures valid PEM markers and a recognized label are present. |
| 45 | + let _ = pem_rfc7468::decode_label(data)?; |
| 46 | + let mut raw_data = Vec::new(); |
| 47 | + let result = Decoder::new(data); |
| 48 | + match result { |
| 49 | + Ok(mut decoder) => decoder.decode_to_end(&mut raw_data)?, |
| 50 | + _ => { |
| 51 | + let cleaned_data = clean_pem_bytes_for_parsing(data)?; |
| 52 | + let mut decoder = Decoder::new(&cleaned_data)?; |
| 53 | + decoder.decode_to_end(&mut raw_data)? |
| 54 | + } |
| 55 | + }; |
| 56 | + if algorithm.signature_len() != raw_data.len() { |
| 57 | + return Err(SpxError::BadSigLength(raw_data.len())); |
| 58 | + } |
| 59 | + Ok(SpxRawSignature { raw_data }) |
| 60 | + } |
| 61 | + |
| 62 | + /// Returns the raw signature bytes. |
| 63 | + pub fn as_bytes(&self) -> &[u8] { |
| 64 | + self.raw_data.as_slice() |
| 65 | + } |
| 66 | +} |
0 commit comments