use crate::crypto::{PKC_CANON_SECRET_KEY_LEN, PKC_SIGNATURE_LEN};
use crate::error::{Error, ErrorCode};
use der::asn1::AnyRef;
use der::{Decode, Header, SliceReader, Tag, Tagged};
const P256_FE_LEN: usize = PKC_CANON_SECRET_KEY_LEN;
const RAW_SIGNATURE_LEN: usize = PKC_SIGNATURE_LEN;
pub fn ecdsa_der_to_raw(der: &[u8]) -> Result<[u8; RAW_SIGNATURE_LEN], Error> {
let mut reader = SliceReader::new(der).map_err(|_| Error::from(ErrorCode::Invalid))?;
let seq_header = Header::decode(&mut reader).map_err(|_| Error::from(ErrorCode::Invalid))?;
if seq_header.tag != Tag::Sequence {
return Err(ErrorCode::Invalid.into());
}
let r_any = AnyRef::decode(&mut reader).map_err(|_| Error::from(ErrorCode::Invalid))?;
if r_any.tag() != Tag::Integer {
return Err(ErrorCode::Invalid.into());
}
let s_any = AnyRef::decode(&mut reader).map_err(|_| Error::from(ErrorCode::Invalid))?;
if s_any.tag() != Tag::Integer {
return Err(ErrorCode::Invalid.into());
}
let mut raw = [0u8; RAW_SIGNATURE_LEN];
copy_integer_to_fixed(&mut raw[..P256_FE_LEN], r_any.value())?;
copy_integer_to_fixed(&mut raw[P256_FE_LEN..], s_any.value())?;
Ok(raw)
}
pub fn copy_integer_to_fixed(target: &mut [u8], integer: &[u8]) -> Result<(), Error> {
let mut src = integer;
while src.len() > 1 && src[0] == 0 {
src = &src[1..];
}
if src.len() > target.len() {
return Err(ErrorCode::Invalid.into());
}
let offset = target.len() - src.len();
target[..offset].fill(0);
target[offset..].copy_from_slice(src);
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ecdsa_der_to_raw_basic() {
let mut der = [0u8; 70];
let r = [0x01u8; 32];
let s = [0x02u8; 32];
der[0] = 0x30; der[1] = 68;
der[2] = 0x02; der[3] = 32;
der[4..36].copy_from_slice(&r);
der[36] = 0x02; der[37] = 32;
der[38..70].copy_from_slice(&s);
let raw = unwrap!(ecdsa_der_to_raw(&der[..70]));
assert_eq!(&raw[..32], &r);
assert_eq!(&raw[32..], &s);
}
#[test]
fn test_ecdsa_der_to_raw_with_leading_zeros() {
let mut der = [0u8; 72];
let r = [0x80u8; 32]; let s = [0x01u8; 32];
der[0] = 0x30; der[1] = 69; der[2] = 0x02; der[3] = 33;
der[4] = 0x00; der[5..37].copy_from_slice(&r);
der[37] = 0x02; der[38] = 32;
der[39..71].copy_from_slice(&s);
let raw = unwrap!(ecdsa_der_to_raw(&der[..71]));
assert_eq!(&raw[..32], &r);
assert_eq!(&raw[32..], &s);
}
#[test]
fn test_ecdsa_der_to_raw_short_integer() {
let mut der = [0u8; 70];
let r = [0x42u8; 32];
let s_short = [0x05u8; 31];
der[0] = 0x30;
der[1] = 67; der[2] = 0x02;
der[3] = 32;
der[4..36].copy_from_slice(&r);
der[36] = 0x02;
der[37] = 31;
der[38..69].copy_from_slice(&s_short);
let raw = unwrap!(ecdsa_der_to_raw(&der[..69]));
assert_eq!(&raw[..32], &r);
assert_eq!(raw[32], 0x00); assert_eq!(&raw[33..], &s_short);
}
#[test]
fn test_copy_integer_to_fixed_strips_leading_zeros() {
let mut target = [0u8; 4];
let integer = [0x00, 0x00, 0x12, 0x34];
unwrap!(copy_integer_to_fixed(&mut target, &integer));
assert_eq!(target, [0x00, 0x00, 0x12, 0x34]);
}
#[test]
fn test_copy_integer_to_fixed_pads_short_values() {
let mut target = [0u8; 4];
let integer = [0x12, 0x34];
unwrap!(copy_integer_to_fixed(&mut target, &integer));
assert_eq!(target, [0x00, 0x00, 0x12, 0x34]);
}
#[test]
fn test_copy_integer_to_fixed_error_on_overflow() {
let mut target = [0u8; 4];
let integer = [0x01, 0x02, 0x03, 0x04, 0x05];
let result = copy_integer_to_fixed(&mut target, &integer);
assert!(result.is_err());
}
}