no bug - Import translations from android-l10n r=release a=l10n CLOSED TREE
[gecko.git] / security / manager / ssl / rsclientcerts / src / util.rs
blob114a74754717f3874f2e34c6931adff5719a9b37
1 /* -*- Mode: rust; rust-indent-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 use byteorder::{BigEndian, NativeEndian, ReadBytesExt, WriteBytesExt};
7 use std::convert::TryInto;
9 use crate::error::{Error, ErrorType};
10 use crate::error_here;
12 /// Accessing fields of packed structs is unsafe (it may be undefined behavior if the field isn't
13 /// aligned). Since we're implementing a PKCS#11 module, we already have to trust the caller not to
14 /// give us bad data, so normally we would deal with this by adding an unsafe block. If we do that,
15 /// though, the compiler complains that the unsafe block is unnecessary. Thus, we use this macro to
16 /// annotate the unsafe block to silence the compiler.
17 #[macro_export]
18 macro_rules! unsafe_packed_field_access {
19     ($e:expr) => {{
20         #[allow(unused_unsafe)]
21         let tmp = unsafe { $e };
22         tmp
23     }};
26 // The following ENCODED_OID_BYTES_* consist of the encoded bytes of an ASN.1
27 // OBJECT IDENTIFIER specifying the indicated OID (in other words, the full
28 // tag, length, and value).
29 #[cfg(any(target_os = "macos", target_os = "ios"))]
30 pub const ENCODED_OID_BYTES_SECP256R1: &[u8] =
31     &[0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07];
32 #[cfg(any(target_os = "macos", target_os = "ios"))]
33 pub const ENCODED_OID_BYTES_SECP384R1: &[u8] = &[0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22];
34 #[cfg(any(target_os = "macos", target_os = "ios"))]
35 pub const ENCODED_OID_BYTES_SECP521R1: &[u8] = &[0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23];
37 // The following OID_BYTES_* consist of the contents of the bytes of an ASN.1
38 // OBJECT IDENTIFIER specifying the indicated OID (in other words, just the
39 // value, and not the tag or length).
40 #[cfg(any(target_os = "macos", target_os = "ios"))]
41 pub const OID_BYTES_SHA_256: &[u8] = &[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01];
42 #[cfg(any(target_os = "macos", target_os = "ios"))]
43 pub const OID_BYTES_SHA_384: &[u8] = &[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02];
44 #[cfg(any(target_os = "macos", target_os = "ios"))]
45 pub const OID_BYTES_SHA_512: &[u8] = &[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03];
46 #[cfg(any(target_os = "macos", target_os = "ios"))]
47 pub const OID_BYTES_SHA_1: &[u8] = &[0x2b, 0x0e, 0x03, 0x02, 0x1a];
49 // This is a helper function to take a value and lay it out in memory how
50 // PKCS#11 is expecting it.
51 pub fn serialize_uint<T: TryInto<u64>>(value: T) -> Result<Vec<u8>, Error> {
52     let value_size = std::mem::size_of::<T>();
53     let mut value_buf = Vec::with_capacity(value_size);
54     let value_as_u64 = value
55         .try_into()
56         .map_err(|_| error_here!(ErrorType::ValueTooLarge))?;
57     value_buf
58         .write_uint::<NativeEndian>(value_as_u64, value_size)
59         .map_err(|_| error_here!(ErrorType::LibraryFailure))?;
60     Ok(value_buf)
63 /// Given a slice of DER bytes representing an RSA public key, extracts the bytes of the modulus
64 /// as an unsigned integer. Also verifies that the public exponent is present (again as an
65 /// unsigned integer). Finally verifies that reading these values consumes the entirety of the
66 /// slice.
67 /// RSAPublicKey ::= SEQUENCE {
68 ///     modulus           INTEGER,  -- n
69 ///     publicExponent    INTEGER   -- e
70 /// }
71 pub fn read_rsa_modulus(public_key: &[u8]) -> Result<Vec<u8>, Error> {
72     let mut sequence = Sequence::new(public_key)?;
73     let modulus_value = sequence.read_unsigned_integer()?;
74     let _exponent = sequence.read_unsigned_integer()?;
75     if !sequence.at_end() {
76         return Err(error_here!(ErrorType::ExtraInput));
77     }
78     Ok(modulus_value.to_vec())
81 /// Given a slice of DER bytes representing a DigestInfo, extracts the bytes of
82 /// the OID of the hash algorithm and the digest.
83 /// DigestInfo ::= SEQUENCE {
84 ///   digestAlgorithm DigestAlgorithmIdentifier,
85 ///   digest Digest }
86 ///
87 /// DigestAlgorithmIdentifier ::= AlgorithmIdentifier
88 ///
89 /// AlgorithmIdentifier  ::=  SEQUENCE  {
90 ///      algorithm               OBJECT IDENTIFIER,
91 ///      parameters              ANY DEFINED BY algorithm OPTIONAL  }
92 ///
93 /// Digest ::= OCTET STRING
94 pub fn read_digest_info(digest_info: &[u8]) -> Result<(&[u8], &[u8]), Error> {
95     let mut sequence = Sequence::new(digest_info)?;
96     let mut algorithm = sequence.read_sequence()?;
97     let oid = algorithm.read_oid()?;
98     algorithm.read_null()?;
99     if !algorithm.at_end() {
100         return Err(error_here!(ErrorType::ExtraInput));
101     }
102     let digest = sequence.read_octet_string()?;
103     if !sequence.at_end() {
104         return Err(error_here!(ErrorType::ExtraInput));
105     }
106     Ok((oid, digest))
109 /// Given a slice of DER bytes representing an ECDSA signature, extracts the bytes of `r` and `s`
110 /// as unsigned integers. Also verifies that this consumes the entirety of the slice.
111 ///   Ecdsa-Sig-Value  ::=  SEQUENCE  {
112 ///        r     INTEGER,
113 ///        s     INTEGER  }
114 #[cfg(any(target_os = "macos", target_os = "ios"))]
115 pub fn read_ec_sig_point(signature: &[u8]) -> Result<(&[u8], &[u8]), Error> {
116     let mut sequence = Sequence::new(signature)?;
117     let r = sequence.read_unsigned_integer()?;
118     let s = sequence.read_unsigned_integer()?;
119     if !sequence.at_end() {
120         return Err(error_here!(ErrorType::ExtraInput));
121     }
122     Ok((r, s))
125 /// Given a slice of DER bytes representing an X.509 certificate, extracts the encoded serial
126 /// number, issuer, and subject. Does not verify that the remainder of the certificate is in any
127 /// way well-formed.
128 ///   Certificate  ::=  SEQUENCE  {
129 ///           tbsCertificate       TBSCertificate,
130 ///           signatureAlgorithm   AlgorithmIdentifier,
131 ///           signatureValue       BIT STRING  }
133 ///   TBSCertificate  ::=  SEQUENCE  {
134 ///           version         [0]  EXPLICIT Version DEFAULT v1,
135 ///           serialNumber         CertificateSerialNumber,
136 ///           signature            AlgorithmIdentifier,
137 ///           issuer               Name,
138 ///           validity             Validity,
139 ///           subject              Name,
140 ///           ...
142 ///   CertificateSerialNumber  ::=  INTEGER
144 ///   Name ::= CHOICE { -- only one possibility for now --
145 ///     rdnSequence  RDNSequence }
147 ///   RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
149 ///   Validity ::= SEQUENCE {
150 ///        notBefore      Time,
151 ///        notAfter       Time  }
152 #[allow(clippy::type_complexity)]
153 pub fn read_encoded_certificate_identifiers(
154     certificate: &[u8],
155 ) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>), Error> {
156     let mut certificate_sequence = Sequence::new(certificate)?;
157     let mut tbs_certificate_sequence = certificate_sequence.read_sequence()?;
158     let _version = tbs_certificate_sequence.read_tagged_value(0)?;
159     let serial_number = tbs_certificate_sequence.read_encoded_sequence_component(INTEGER)?;
160     let _signature = tbs_certificate_sequence.read_sequence()?;
161     let issuer =
162         tbs_certificate_sequence.read_encoded_sequence_component(SEQUENCE | CONSTRUCTED)?;
163     let _validity = tbs_certificate_sequence.read_sequence()?;
164     let subject =
165         tbs_certificate_sequence.read_encoded_sequence_component(SEQUENCE | CONSTRUCTED)?;
166     Ok((serial_number, issuer, subject))
169 /// Helper macro for reading some bytes from a slice while checking the slice is long enough.
170 /// Returns a pair consisting of a slice of the bytes read and a slice of the rest of the bytes
171 /// from the original slice.
172 macro_rules! try_read_bytes {
173     ($data:ident, $len:expr) => {{
174         if $data.len() < $len {
175             return Err(error_here!(ErrorType::TruncatedInput));
176         }
177         $data.split_at($len)
178     }};
181 /// ASN.1 tag identifying an integer.
182 const INTEGER: u8 = 0x02;
183 /// ASN.1 tag identifying an octet string.
184 const OCTET_STRING: u8 = 0x04;
185 /// ASN.1 tag identifying a null value.
186 const NULL: u8 = 0x05;
187 /// ASN.1 tag identifying an object identifier (OID).
188 const OBJECT_IDENTIFIER: u8 = 0x06;
189 /// ASN.1 tag identifying a sequence.
190 const SEQUENCE: u8 = 0x10;
191 /// ASN.1 tag modifier identifying an item as constructed.
192 const CONSTRUCTED: u8 = 0x20;
193 /// ASN.1 tag modifier identifying an item as context-specific.
194 const CONTEXT_SPECIFIC: u8 = 0x80;
196 /// A helper struct for reading items from a DER SEQUENCE (in this case, all sequences are
197 /// assumed to be CONSTRUCTED).
198 struct Sequence<'a> {
199     /// The contents of the SEQUENCE.
200     contents: Der<'a>,
203 impl<'a> Sequence<'a> {
204     fn new(input: &'a [u8]) -> Result<Sequence<'a>, Error> {
205         let mut der = Der::new(input);
206         let (_, _, sequence_bytes) = der.read_tlv(SEQUENCE | CONSTRUCTED)?;
207         // We're assuming we want to consume the entire input for now.
208         if !der.at_end() {
209             return Err(error_here!(ErrorType::ExtraInput));
210         }
211         Ok(Sequence {
212             contents: Der::new(sequence_bytes),
213         })
214     }
216     // TODO: we're not exhaustively validating this integer
217     fn read_unsigned_integer(&mut self) -> Result<&'a [u8], Error> {
218         let (_, _, bytes) = self.contents.read_tlv(INTEGER)?;
219         if bytes.is_empty() {
220             return Err(error_here!(ErrorType::InvalidInput));
221         }
222         // There may be a leading zero (we should also check that the first bit
223         // of the rest of the integer is set).
224         if bytes[0] == 0 && bytes.len() > 1 {
225             let (_, integer) = bytes.split_at(1);
226             Ok(integer)
227         } else {
228             Ok(bytes)
229         }
230     }
232     fn read_octet_string(&mut self) -> Result<&'a [u8], Error> {
233         let (_, _, bytes) = self.contents.read_tlv(OCTET_STRING)?;
234         Ok(bytes)
235     }
237     fn read_oid(&mut self) -> Result<&'a [u8], Error> {
238         let (_, _, bytes) = self.contents.read_tlv(OBJECT_IDENTIFIER)?;
239         Ok(bytes)
240     }
242     fn read_null(&mut self) -> Result<(), Error> {
243         let (_, _, bytes) = self.contents.read_tlv(NULL)?;
244         if bytes.is_empty() {
245             Ok(())
246         } else {
247             Err(error_here!(ErrorType::InvalidInput))
248         }
249     }
251     fn read_sequence(&mut self) -> Result<Sequence<'a>, Error> {
252         let (_, _, sequence_bytes) = self.contents.read_tlv(SEQUENCE | CONSTRUCTED)?;
253         Ok(Sequence {
254             contents: Der::new(sequence_bytes),
255         })
256     }
258     fn read_tagged_value(&mut self, tag: u8) -> Result<&'a [u8], Error> {
259         let (_, _, tagged_value_bytes) = self
260             .contents
261             .read_tlv(CONTEXT_SPECIFIC | CONSTRUCTED | tag)?;
262         Ok(tagged_value_bytes)
263     }
265     fn read_encoded_sequence_component(&mut self, tag: u8) -> Result<Vec<u8>, Error> {
266         let (tag, length, value) = self.contents.read_tlv(tag)?;
267         let mut encoded_component_bytes = length;
268         encoded_component_bytes.insert(0, tag);
269         encoded_component_bytes.extend_from_slice(value);
270         Ok(encoded_component_bytes)
271     }
273     fn at_end(&self) -> bool {
274         self.contents.at_end()
275     }
278 /// A helper struct for reading DER data. The contents are treated like a cursor, so its position
279 /// is updated as data is read.
280 struct Der<'a> {
281     contents: &'a [u8],
284 impl<'a> Der<'a> {
285     fn new(contents: &'a [u8]) -> Der<'a> {
286         Der { contents }
287     }
289     // In theory, a caller could encounter an error and try another operation, in which case we may
290     // be in an inconsistent state. As long as this implementation isn't exposed to code that would
291     // use it incorrectly (i.e. it stays in this module and we only expose a stateless API), it
292     // should be safe.
293     /// Given an expected tag, reads the next (tag, lengh, value) from the contents. Most
294     /// consumers will only be interested in the value, but some may want the entire encoded
295     /// contents, in which case the returned tuple can be concatenated.
296     fn read_tlv(&mut self, tag: u8) -> Result<(u8, Vec<u8>, &'a [u8]), Error> {
297         let contents = self.contents;
298         let (tag_read, rest) = try_read_bytes!(contents, 1);
299         if tag_read[0] != tag {
300             return Err(error_here!(ErrorType::InvalidInput));
301         }
302         let mut accumulated_length_bytes = Vec::with_capacity(4);
303         let (length1, rest) = try_read_bytes!(rest, 1);
304         accumulated_length_bytes.extend_from_slice(length1);
305         let (length, to_read_from) = if length1[0] < 0x80 {
306             (length1[0] as usize, rest)
307         } else if length1[0] == 0x81 {
308             let (length, rest) = try_read_bytes!(rest, 1);
309             accumulated_length_bytes.extend_from_slice(length);
310             if length[0] < 0x80 {
311                 return Err(error_here!(ErrorType::InvalidInput));
312             }
313             (length[0] as usize, rest)
314         } else if length1[0] == 0x82 {
315             let (mut lengths, rest) = try_read_bytes!(rest, 2);
316             accumulated_length_bytes.extend_from_slice(lengths);
317             let length = lengths
318                 .read_u16::<BigEndian>()
319                 .map_err(|_| error_here!(ErrorType::LibraryFailure))?;
320             if length < 256 {
321                 return Err(error_here!(ErrorType::InvalidInput));
322             }
323             (length as usize, rest)
324         } else {
325             return Err(error_here!(ErrorType::UnsupportedInput));
326         };
327         let (contents, rest) = try_read_bytes!(to_read_from, length);
328         self.contents = rest;
329         Ok((tag, accumulated_length_bytes, contents))
330     }
332     fn at_end(&self) -> bool {
333         self.contents.is_empty()
334     }
337 #[cfg(test)]
338 mod tests {
339     use super::*;
341     #[test]
342     fn der_test_empty_input() {
343         let input = Vec::new();
344         let mut der = Der::new(&input);
345         assert!(der.read_tlv(INTEGER).is_err());
346     }
348     #[test]
349     fn der_test_no_length() {
350         let input = vec![INTEGER];
351         let mut der = Der::new(&input);
352         assert!(der.read_tlv(INTEGER).is_err());
353     }
355     #[test]
356     fn der_test_empty_sequence() {
357         let input = vec![SEQUENCE, 0];
358         let mut der = Der::new(&input);
359         let read_result = der.read_tlv(SEQUENCE);
360         assert!(read_result.is_ok());
361         let (tag, length, sequence_bytes) = read_result.unwrap();
362         assert_eq!(tag, SEQUENCE);
363         assert_eq!(length, vec![0]);
364         assert_eq!(sequence_bytes.len(), 0);
365         assert!(der.at_end());
366     }
368     #[test]
369     fn der_test_not_at_end() {
370         let input = vec![SEQUENCE, 0, 1];
371         let mut der = Der::new(&input);
372         let read_result = der.read_tlv(SEQUENCE);
373         assert!(read_result.is_ok());
374         let (tag, length, sequence_bytes) = read_result.unwrap();
375         assert_eq!(tag, SEQUENCE);
376         assert_eq!(length, vec![0]);
377         assert_eq!(sequence_bytes.len(), 0);
378         assert!(!der.at_end());
379     }
381     #[test]
382     fn der_test_wrong_tag() {
383         let input = vec![SEQUENCE, 0];
384         let mut der = Der::new(&input);
385         assert!(der.read_tlv(INTEGER).is_err());
386     }
388     #[test]
389     fn der_test_truncated_two_byte_length() {
390         let input = vec![SEQUENCE, 0x81];
391         let mut der = Der::new(&input);
392         assert!(der.read_tlv(SEQUENCE).is_err());
393     }
395     #[test]
396     fn der_test_truncated_three_byte_length() {
397         let input = vec![SEQUENCE, 0x82, 1];
398         let mut der = Der::new(&input);
399         assert!(der.read_tlv(SEQUENCE).is_err());
400     }
402     #[test]
403     fn der_test_truncated_data() {
404         let input = vec![SEQUENCE, 20, 1];
405         let mut der = Der::new(&input);
406         assert!(der.read_tlv(SEQUENCE).is_err());
407     }
409     #[test]
410     fn der_test_sequence() {
411         let input = vec![
412             SEQUENCE, 20, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 0, 0,
413         ];
414         let mut der = Der::new(&input);
415         let result = der.read_tlv(SEQUENCE);
416         assert!(result.is_ok());
417         let (tag, length, value) = result.unwrap();
418         assert_eq!(tag, SEQUENCE);
419         assert_eq!(length, vec![20]);
420         assert_eq!(
421             value,
422             [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 0, 0]
423         );
424         assert!(der.at_end());
425     }
427     #[test]
428     fn der_test_not_shortest_two_byte_length_encoding() {
429         let input = vec![SEQUENCE, 0x81, 1, 1];
430         let mut der = Der::new(&input);
431         assert!(der.read_tlv(SEQUENCE).is_err());
432     }
434     #[test]
435     fn der_test_not_shortest_three_byte_length_encoding() {
436         let input = vec![SEQUENCE, 0x82, 0, 1, 1];
437         let mut der = Der::new(&input);
438         assert!(der.read_tlv(SEQUENCE).is_err());
439     }
441     #[test]
442     fn der_test_indefinite_length_unsupported() {
443         let input = vec![SEQUENCE, 0x80, 1, 2, 3, 0x00, 0x00];
444         let mut der = Der::new(&input);
445         assert!(der.read_tlv(SEQUENCE).is_err());
446     }
448     #[test]
449     fn der_test_input_too_long() {
450         // This isn't valid DER (the contents of the SEQUENCE are truncated), but it demonstrates
451         // that we don't try to read too much if we're given a long length (and also that we don't
452         // support lengths 2^16 and up).
453         let input = vec![SEQUENCE, 0x83, 0x01, 0x00, 0x01, 1, 1, 1, 1];
454         let mut der = Der::new(&input);
455         assert!(der.read_tlv(SEQUENCE).is_err());
456     }
458     #[test]
459     fn empty_input_fails() {
460         let empty = Vec::new();
461         assert!(read_rsa_modulus(&empty).is_err());
462         #[cfg(any(target_os = "macos", target_os = "ios"))]
463         assert!(read_ec_sig_point(&empty).is_err());
464         assert!(read_encoded_certificate_identifiers(&empty).is_err());
465     }
467     #[test]
468     fn empty_sequence_fails() {
469         let empty = vec![SEQUENCE | CONSTRUCTED];
470         assert!(read_rsa_modulus(&empty).is_err());
471         #[cfg(any(target_os = "macos", target_os = "ios"))]
472         assert!(read_ec_sig_point(&empty).is_err());
473         assert!(read_encoded_certificate_identifiers(&empty).is_err());
474     }
476     #[test]
477     fn test_read_rsa_modulus() {
478         let rsa_key = include_bytes!("../test/rsa.bin");
479         let result = read_rsa_modulus(rsa_key);
480         assert!(result.is_ok());
481         let modulus = result.unwrap();
482         assert_eq!(modulus, include_bytes!("../test/modulus.bin").to_vec());
483     }
485     #[test]
486     fn test_read_certificate_identifiers() {
487         let certificate = include_bytes!("../test/certificate.bin");
488         let result = read_encoded_certificate_identifiers(certificate);
489         assert!(result.is_ok());
490         let (serial_number, issuer, subject) = result.unwrap();
491         assert_eq!(
492             serial_number,
493             &[
494                 0x02, 0x14, 0x3f, 0xed, 0x7b, 0x43, 0x47, 0x8a, 0x53, 0x42, 0x5b, 0x0d, 0x50, 0xe1,
495                 0x37, 0x88, 0x2a, 0x20, 0x3f, 0x31, 0x17, 0x20
496             ]
497         );
498         assert_eq!(
499             issuer,
500             &[
501                 0x30, 0x12, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x54,
502                 0x65, 0x73, 0x74, 0x20, 0x43, 0x41
503             ]
504         );
505         assert_eq!(
506             subject,
507             &[
508                 0x30, 0x1a, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x54,
509                 0x65, 0x73, 0x74, 0x20, 0x45, 0x6e, 0x64, 0x2d, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79
510             ]
511         );
512     }
514     #[test]
515     #[cfg(target_os = "windows")]
516     fn test_read_digest() {
517         // SEQUENCE
518         //   SEQUENCE
519         //     OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256
520         //       NULL
521         //   OCTET STRING 1A7FCDB9A5F649F954885CFE145F3E93F0D1FA72BE980CC6EC82C70E1407C7D2
522         let digest_info = [
523             0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x1, 0x65, 0x03, 0x04, 0x02,
524             0x01, 0x05, 0x00, 0x04, 0x20, 0x1a, 0x7f, 0xcd, 0xb9, 0xa5, 0xf6, 0x49, 0xf9, 0x54,
525             0x88, 0x5c, 0xfe, 0x14, 0x5f, 0x3e, 0x93, 0xf0, 0xd1, 0xfa, 0x72, 0xbe, 0x98, 0x0c,
526             0xc6, 0xec, 0x82, 0xc7, 0x0e, 0x14, 0x07, 0xc7, 0xd2,
527         ];
528         let result = read_digest(&digest_info);
529         assert!(result.is_ok());
530         let digest = result.unwrap();
531         assert_eq!(
532             digest,
533             &[
534                 0x1a, 0x7f, 0xcd, 0xb9, 0xa5, 0xf6, 0x49, 0xf9, 0x54, 0x88, 0x5c, 0xfe, 0x14, 0x5f,
535                 0x3e, 0x93, 0xf0, 0xd1, 0xfa, 0x72, 0xbe, 0x98, 0x0c, 0xc6, 0xec, 0x82, 0xc7, 0x0e,
536                 0x14, 0x07, 0xc7, 0xd2
537             ]
538         );
539     }