spideroak_crypto/
asn1.rs

1//! ASN.1 utility routines.
2
3#![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/// An error returned when a signature's encoding is invalid.
23#[derive(Debug, Eq, PartialEq)]
24pub enum EncodingError {
25    /// An unknown or internal error has occurred.
26    Other(&'static str),
27    /// Either `r` or `s` are too large.
28    OutOfRange,
29    /// Unable to parse an ASN.1 DER encoded signature.
30    Der(der::Error),
31    /// The input is too large.
32    TooLarge,
33    /// An implementaion error.
34    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
69/// An ASN.1 DER encoded ECDSA signature.
70///
71/// `N` should be the maximum number of bytes required by the
72/// signature. This figure can be determined with
73/// [`max_sig_len`].
74pub struct Sig<S: ?Sized, const N: usize> {
75    /// The ASN.1 DER encoded signature.
76    ///
77    /// Do not use this field directly; use `Self::as_bytes`
78    /// instead. Signatures do not have a fixed size, only
79    /// a maximum. Only `len` bytes are valid; the remaining
80    /// bytes are undefined.
81    sig: [u8; N],
82    /// The number of bytes used in `sig`.
83    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    // Validates the encoding of `der`.
99    fn check(der: &[u8]) -> Result<(), EncodingError> {
100        // sig := SEQUENCE || R || S
101        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    /// Creates a [`Sig`] from the DER-encoded signature `der`.
114    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    /// Converts the DER-encoded signature to a 'raw' signature.
130    pub fn to_raw<const M: usize>(&self) -> Result<RawSig<M>, EncodingError> {
131        RawSig::from_der(self.borrow())
132    }
133
134    /// Converts a raw signature to a DER-encoded signature.
135    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        // The Length type has an add method that is checked for overflow.
141        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    /// Returns the signature as bytes.
154    ///
155    /// The length of the result will be in `[0, N)`.
156    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/// A 'raw' ECDSA signature.
197///
198/// `N` should be the maximum number of bytes required by the
199/// signature. This figure can be determined with
200/// [`raw_sig_len`].
201///
202/// `N` must be a power of two in the range `[2, 2^31]`.
203#[derive(Copy, Clone, Debug)]
204pub struct RawSig<const N: usize>([u8; N]);
205
206impl<const N: usize> RawSig<N> {
207    /// Forces a compilation error when `N` is out of range.
208    const fn check() {
209        const {
210            assert!(
211                // Obvious case.
212                N > 0  &&
213                // It is impossible to have an odd-length raw ECDSA
214                // signature since it would mean that the integers have
215                // different lengths.
216                N % 2 == 0  &&
217                // There aren't any curves with integers this short that
218                // also have at least 128 bits of security.
219                N/2 >= 32 &&
220                // This ensures that we can convert `r` and `s` to DER
221                // `INTEGER`s, which have an upper bound of 2^32 octets.
222                // There aren't any curves with integers this long, so it
223                // won't affect any implementations.
224                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    /// Returns `(r, s)`.
252    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    /// Creates a [`RawSig`] from its ASN.1 DER encoding.
262    fn from_der(der: &[u8]) -> Result<Self, EncodingError> {
263        Self::check();
264
265        // sig := SEQUENCE || R || S
266        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    /// Creates a [`RawSig`] from `(r, s)`.
281    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            // Left pad with zeros since these are big-endian
291            // integers.
292            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
312/// Returns the maximum size in bytes of a DER-encoded ECDSA
313/// signature for a curve with a `bits` long field element
314/// (scalar).
315pub const fn max_sig_len<const BITS: usize>() -> usize {
316    const {
317        // Length of an integer
318        //    tag || DER(len) || len
319        let n = 1 + der_len(BITS + 1) + 1 + BITS;
320        // ECDSA signatures are two integers
321        //    r || s
322        let v = 2 * n;
323        // DER header
324        //    tag || DER(len) || len
325        1 + der_len(v) + v
326    }
327}
328
329/// Returns the number of bits necessary to DER encode `n`.
330const fn der_len(n: usize) -> usize {
331    if n < 0x80 {
332        1
333    } else {
334        // The following expression can never wrap
335        (n.ilog2() as usize).wrapping_add(7) / 8
336    }
337}
338
339/// Returns the maximum size in bytes of a 'raw' ECDSA signature
340/// for a curve with a `bits` long field element (scalar).
341pub const fn raw_sig_len(bits: usize) -> usize {
342    let extra_byte = bits % 8 != 0;
343    // The following expressions can never wrap
344    let bytes = (bits / 8).wrapping_add(if extra_byte { 1 } else { 0 });
345    // r || s
346    bytes.wrapping_mul(2)
347}