1#![forbid(unsafe_code)]
4
5use core::{
6 borrow::Borrow,
7 fmt::{self, Debug},
8 marker::PhantomData,
9 ops::Add,
10 result::Result,
11};
12
13use buggy::{Bug, BugExt};
14use der::{asn1::UintRef, Decode, Encode, Header, Reader, SliceReader, SliceWriter, Tag};
15
16use crate::{
17 import::{Import, ImportError},
18 signer::{Signature, Signer},
19 util::copy,
20};
21
22#[derive(Debug, Eq, PartialEq)]
24pub enum EncodingError {
25 Other(&'static str),
27 OutOfRange,
29 Der(der::Error),
31 TooLarge,
33 Bug(Bug),
35}
36
37impl fmt::Display for EncodingError {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 match self {
40 Self::Other(msg) => write!(f, "{}", msg),
41 Self::OutOfRange => write!(f, "integer out of range"),
42 Self::Der(err) => write!(f, "{}", err),
43 Self::TooLarge => write!(f, "DER input too large"),
44 Self::Bug(bug) => write!(f, "implementaion bug: {}", bug.msg()),
45 }
46 }
47}
48
49impl core::error::Error for EncodingError {}
50
51impl From<der::Error> for EncodingError {
52 fn from(err: der::Error) -> Self {
53 Self::Der(err)
54 }
55}
56
57impl From<EncodingError> for ImportError {
58 fn from(_err: EncodingError) -> Self {
59 Self::InvalidSyntax
60 }
61}
62
63impl From<Bug> for EncodingError {
64 fn from(bug: Bug) -> Self {
65 Self::Bug(bug)
66 }
67}
68
69pub struct Sig<S: ?Sized, const N: usize> {
75 sig: [u8; N],
82 len: usize,
84 _s: PhantomData<S>,
85}
86
87impl<S: Signer + ?Sized, const N: usize> Clone for Sig<S, N> {
88 fn clone(&self) -> Self {
89 Self {
90 sig: self.sig,
91 len: self.len,
92 _s: PhantomData,
93 }
94 }
95}
96
97impl<S: Signer + ?Sized, const N: usize> Sig<S, N> {
98 fn check(der: &[u8]) -> Result<(), EncodingError> {
100 let mut rd = SliceReader::new(der)?;
102 let hdr = Header::decode(&mut rd)?;
103 hdr.tag.assert_eq(Tag::Sequence)?;
104
105 rd.read_nested(hdr.length, |rd| {
106 UintRef::decode(rd)?;
107 UintRef::decode(rd)?;
108 Ok(())
109 })?;
110 Ok(rd.finish(())?)
111 }
112
113 pub fn new(der: &[u8]) -> Result<Self, EncodingError> {
115 if der.len() > N {
116 Err(EncodingError::TooLarge)
117 } else {
118 Self::check(der)?;
119 let mut sig = [0u8; N];
120 let len = copy(&mut sig, der);
121 Ok(Self {
122 sig,
123 len,
124 _s: PhantomData,
125 })
126 }
127 }
128
129 pub fn to_raw<const M: usize>(&self) -> Result<RawSig<M>, EncodingError> {
131 RawSig::from_der(self.borrow())
132 }
133
134 pub fn from_raw<const R: usize>(raw: RawSig<R>) -> Result<Self, EncodingError> {
136 let (r, s) = raw.integers();
137
138 let mut sig = [0u8; N];
139 let mut w = SliceWriter::new(&mut sig);
140 w.sequence((r.encoded_len()?.add(s.encoded_len()?))?, |seq| {
142 seq.encode(&r)?;
143 seq.encode(&s)
144 })?;
145 let len = w.finish()?.len();
146 Ok(Sig {
147 sig,
148 len,
149 _s: PhantomData,
150 })
151 }
152
153 pub fn as_bytes(&self) -> &[u8] {
157 &self.sig[..self.len]
158 }
159}
160
161impl<S: Signer + ?Sized, const N: usize> Signature<S> for Sig<S, N> {
162 type Data = Self;
163
164 fn export(&self) -> Self::Data {
165 self.clone()
166 }
167}
168
169impl<S: Signer + ?Sized, const N: usize> Borrow<[u8]> for Sig<S, N> {
170 fn borrow(&self) -> &[u8] {
171 self.as_bytes()
172 }
173}
174
175impl<S: Signer + ?Sized, const N: usize> Debug for Sig<S, N> {
176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 let s: &[u8] = Sig::borrow(self);
178 s.fmt(f)
179 }
180}
181
182impl<'a, S: Signer + ?Sized, const N: usize> Import<&'a [u8]> for Sig<S, N> {
183 fn import(data: &'a [u8]) -> Result<Self, ImportError> {
184 Self::check(data)?;
185
186 let mut sig = [0u8; N];
187 let len = copy(&mut sig, data);
188 Ok(Self {
189 sig,
190 len,
191 _s: PhantomData,
192 })
193 }
194}
195
196#[derive(Copy, Clone, Debug)]
204pub struct RawSig<const N: usize>([u8; N]);
205
206impl<const N: usize> RawSig<N> {
207 const fn check() {
209 const {
210 assert!(
211 N > 0 &&
213 N % 2 == 0 &&
217 N/2 >= 32 &&
220 N / 2 <= (u32::MAX as usize),
225 "`N` is not a power of two in [2, 2^31]",
226 );
227 }
228 }
229
230 #[cfg(feature = "bearssl")]
231 pub(crate) fn as_mut_ptr(&mut self) -> *mut u8 {
232 Self::check();
233
234 self.0.as_mut_ptr()
235 }
236
237 #[cfg(feature = "bearssl")]
238 pub(crate) fn as_ptr(&self) -> *const u8 {
239 Self::check();
240
241 self.0.as_ptr()
242 }
243
244 #[cfg(feature = "bearssl")]
245 pub(crate) fn len(&self) -> usize {
246 Self::check();
247
248 self.0.len()
249 }
250
251 fn integers(&self) -> (UintRef<'_>, UintRef<'_>) {
253 Self::check();
254
255 let (r, s) = self.0.split_at(self.0.len() / 2);
256 let r = UintRef::new(r).expect("should not occur given the bounds on `N`");
257 let s = UintRef::new(s).expect("should not occur given the bounds on `N`");
258 (r, s)
259 }
260
261 fn from_der(der: &[u8]) -> Result<Self, EncodingError> {
263 Self::check();
264
265 let mut rd = SliceReader::new(der)?;
267 let hdr = Header::decode(&mut rd)?;
268 hdr.tag.assert_eq(Tag::Sequence)?;
269
270 let ret = rd.read_nested(hdr.length, |rd| {
271 let r = UintRef::decode(rd)?;
272 let s = UintRef::decode(rd)?;
273 Ok((r, s))
274 })?;
275
276 let (r, s) = rd.finish(ret)?;
277 RawSig::from_integers(r, s)
278 }
279
280 fn from_integers(r: UintRef<'_>, s: UintRef<'_>) -> Result<Self, EncodingError> {
282 Self::check();
283
284 let r = r.as_bytes();
285 let s = s.as_bytes();
286 if r.len() > N / 2 || s.len() > N / 2 {
287 Err(EncodingError::OutOfRange)
288 } else {
289 let mut raw = [0u8; N];
290 let r_start = N
293 .checked_div(2)
294 .and_then(|half| half.checked_sub(r.len()))
295 .assume("N/2 >= r length")?;
296 copy(&mut raw[r_start..], r);
297 let s_start = N.checked_sub(s.len()).assume("N >= s length")?;
298 copy(&mut raw[s_start..], s);
299 Ok(Self(raw))
300 }
301 }
302}
303
304impl<const N: usize> Default for RawSig<N> {
305 fn default() -> Self {
306 Self::check();
307
308 Self([0u8; N])
309 }
310}
311
312pub const fn max_sig_len<const BITS: usize>() -> usize {
316 const {
317 let n = 1 + der_len(BITS + 1) + 1 + BITS;
320 let v = 2 * n;
323 1 + der_len(v) + v
326 }
327}
328
329const fn der_len(n: usize) -> usize {
331 if n < 0x80 {
332 1
333 } else {
334 (n.ilog2() as usize).wrapping_add(7) / 8
336 }
337}
338
339pub const fn raw_sig_len(bits: usize) -> usize {
342 let extra_byte = bits % 8 != 0;
343 let bytes = (bits / 8).wrapping_add(if extra_byte { 1 } else { 0 });
345 bytes.wrapping_mul(2)
347}