| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| #![allow( |
| clippy::unused_unit, |
| clippy::needless_lifetimes, |
| clippy::redundant_closure |
| )] |
| // Insert std prelude in the top for the sgx feature |
| #[cfg(feature = "mesalock_sgx")] |
| use std::prelude::v1::*; |
| |
| use yasna::ASN1Result; |
| use yasna::{BERReader, BERReaderSeq, BERReaderSet}; |
| use yasna::{DERWriter, DERWriterSeq, DERWriterSet}; |
| |
| pub type Writer<'a> = DERWriter<'a>; |
| pub type Reader<'a, 'b> = BERReader<'a, 'b>; |
| |
| pub trait ConsWriter<'a> { |
| fn next<'b>(&'b mut self) -> Writer<'b>; |
| } |
| |
| pub trait ConsReader<'a, 'b> |
| where |
| 'a: 'b, |
| { |
| fn next<'c>(&'c mut self, tags: &[yasna::Tag]) -> ASN1Result<Reader<'a, 'c>>; |
| } |
| |
| impl<'a> ConsWriter<'a> for DERWriterSeq<'a> { |
| fn next<'b>(&'b mut self) -> Writer<'b> { |
| self.next() |
| } |
| } |
| |
| impl<'a> ConsWriter<'a> for DERWriterSet<'a> { |
| fn next<'b>(&'b mut self) -> Writer<'b> { |
| self.next() |
| } |
| } |
| |
| impl<'a, 'b> ConsReader<'a, 'b> for BERReaderSeq<'a, 'b> { |
| fn next<'c>(&'c mut self, _tags: &[yasna::Tag]) -> ASN1Result<Reader<'a, 'c>> { |
| Ok(self.next()) |
| } |
| } |
| |
| impl<'a, 'b> ConsReader<'a, 'b> for BERReaderSet<'a, 'b> { |
| fn next<'c>(&'c mut self, tags: &[yasna::Tag]) -> ASN1Result<Reader<'a, 'c>> { |
| self.next(tags) |
| } |
| } |
| |
| pub trait Asn1Ty { |
| type ValueTy; |
| const TAG: yasna::Tag; |
| fn dump<'a>(writer: Writer<'a>, value: Self::ValueTy) -> (); |
| fn load<'a, 'b>(reader: Reader<'a, 'b>) -> ASN1Result<Self::ValueTy> |
| where |
| 'a: 'b; |
| } |
| |
| pub trait Asn1ConsTy |
| where |
| Self: std::marker::Sized, |
| { |
| type ValueTy; |
| fn dump<'a, W: ConsWriter<'a>>(writer: &mut W, value: Self::ValueTy) -> (); |
| fn load<'a, 'b, R>(reader: &mut R) -> ASN1Result<Self::ValueTy> |
| where |
| 'a: 'b, |
| R: ConsReader<'a, 'b>; |
| } |
| |
| pub trait Asn1Tag { |
| const TAG: yasna::Tag; |
| } |
| |
| const fn context_tag(tnum: u64) -> yasna::Tag { |
| yasna::Tag { |
| tag_class: yasna::TagClass::ContextSpecific, |
| tag_number: tnum, |
| } |
| } |
| |
| mod no_instance { |
| #![allow(dead_code)] |
| |
| use super::{Asn1ConsTy, Asn1Tag, Asn1Ty}; |
| use std::marker::PhantomData; |
| |
| pub(crate) struct CtxT0; |
| pub(crate) struct CtxT1; |
| pub(crate) struct CtxT3; |
| |
| pub(crate) struct Oid; |
| pub(crate) struct U8; |
| pub(crate) struct I8; |
| pub(crate) struct BigUint; |
| pub(crate) struct Utf8Str; |
| pub(crate) struct UtcTime; |
| pub(crate) struct BitVec; |
| pub(crate) struct Bytes; |
| pub(crate) struct Tagged<T: Asn1Tag, S: Asn1Ty> { |
| t: PhantomData<T>, |
| s: PhantomData<S>, |
| } |
| pub(crate) struct Sequence<U: Asn1Ty, V: Asn1ConsTy> { |
| u: PhantomData<U>, |
| v: PhantomData<V>, |
| } |
| pub(crate) struct Set<U: Asn1Ty, V: Asn1ConsTy> { |
| u: PhantomData<U>, |
| v: PhantomData<V>, |
| } |
| pub(crate) struct Cons<U: Asn1Ty, V: Asn1ConsTy> { |
| u: PhantomData<U>, |
| v: PhantomData<V>, |
| } |
| pub(crate) struct Nil; |
| } |
| |
| use no_instance::*; |
| |
| impl Asn1Tag for CtxT0 { |
| const TAG: yasna::Tag = context_tag(0); |
| } |
| |
| impl Asn1Tag for CtxT1 { |
| const TAG: yasna::Tag = context_tag(1); |
| } |
| |
| impl Asn1Tag for CtxT3 { |
| const TAG: yasna::Tag = context_tag(3); |
| } |
| |
| impl<U: Asn1Ty, V: Asn1ConsTy> Asn1ConsTy for Cons<U, V> { |
| type ValueTy = (U::ValueTy, V::ValueTy); |
| fn dump<'a, W: ConsWriter<'a>>(writer: &mut W, value: Self::ValueTy) -> () { |
| U::dump(writer.next(), value.0); |
| V::dump(writer, value.1); |
| } |
| fn load<'a, 'b, R>(reader: &mut R) -> ASN1Result<Self::ValueTy> |
| where |
| 'a: 'b, |
| R: ConsReader<'a, 'b>, |
| { |
| let first = U::load(reader.next(&[U::TAG])?)?; |
| let second = V::load(reader)?; |
| Ok((first, second)) |
| } |
| } |
| |
| impl Asn1ConsTy for Nil { |
| type ValueTy = (); |
| fn dump<'a, W: ConsWriter<'a>>(_writer: &mut W, _value: Self::ValueTy) -> () {} |
| fn load<'a, 'b, R>(_reader: &mut R) -> ASN1Result<Self::ValueTy> |
| where |
| 'a: 'b, |
| R: ConsReader<'a, 'b>, |
| { |
| Ok(()) |
| } |
| } |
| |
| impl<T: Asn1Tag, S: Asn1Ty> Asn1Ty for Tagged<T, S> { |
| type ValueTy = S::ValueTy; |
| const TAG: yasna::Tag = T::TAG; |
| fn dump<'a>(writer: Writer<'a>, value: Self::ValueTy) { |
| writer.write_tagged(T::TAG, |writer| S::dump(writer, value)); |
| } |
| fn load<'a, 'b>(reader: Reader<'a, 'b>) -> ASN1Result<Self::ValueTy> |
| where |
| 'a: 'b, |
| { |
| reader.read_tagged(T::TAG, |reader| S::load(reader)) |
| } |
| } |
| |
| impl<U: Asn1Ty, V: Asn1ConsTy> Asn1Ty for Sequence<U, V> { |
| type ValueTy = (U::ValueTy, V::ValueTy); |
| const TAG: yasna::Tag = yasna::tags::TAG_SEQUENCE; |
| fn dump<'a>(writer: Writer<'a>, value: Self::ValueTy) { |
| writer.write_sequence(|writer| { |
| U::dump(writer.next(), value.0); |
| V::dump(writer, value.1); |
| }); |
| } |
| fn load<'a, 'b>(reader: Reader<'a, 'b>) -> ASN1Result<Self::ValueTy> |
| where |
| 'a: 'b, |
| { |
| reader.read_sequence(|reader| { |
| let first = U::load(reader.next())?; |
| let second = V::load(reader)?; |
| Ok((first, second)) |
| }) |
| } |
| } |
| |
| impl<U: Asn1Ty, V: Asn1ConsTy> Asn1Ty for Set<U, V> { |
| type ValueTy = (U::ValueTy, V::ValueTy); |
| const TAG: yasna::Tag = yasna::tags::TAG_SET; |
| fn dump<'a>(writer: Writer<'a>, value: Self::ValueTy) { |
| writer.write_set(|writer| { |
| U::dump(writer.next(), value.0); |
| V::dump(writer, value.1); |
| }); |
| } |
| fn load<'a, 'b>(reader: Reader<'a, 'b>) -> ASN1Result<Self::ValueTy> |
| where |
| 'a: 'b, |
| { |
| reader.read_set(|reader| { |
| let first = U::load(reader.next(&[U::TAG])?)?; |
| let second = V::load(reader)?; |
| Ok((first, second)) |
| }) |
| } |
| } |
| |
| impl Asn1Ty for U8 { |
| type ValueTy = u8; |
| const TAG: yasna::Tag = yasna::tags::TAG_INTEGER; |
| fn dump<'a>(writer: Writer<'a>, value: Self::ValueTy) { |
| writer.write_u8(value); |
| } |
| fn load<'a, 'b>(reader: Reader<'a, 'b>) -> ASN1Result<Self::ValueTy> |
| where |
| 'a: 'b, |
| { |
| reader.read_u8() |
| } |
| } |
| |
| impl Asn1Ty for I8 { |
| type ValueTy = i8; |
| const TAG: yasna::Tag = yasna::tags::TAG_INTEGER; |
| fn dump<'a>(writer: Writer<'a>, value: Self::ValueTy) { |
| writer.write_i8(value); |
| } |
| fn load<'a, 'b>(reader: Reader<'a, 'b>) -> ASN1Result<Self::ValueTy> |
| where |
| 'a: 'b, |
| { |
| reader.read_i8() |
| } |
| } |
| |
| impl Asn1Ty for BigUint { |
| type ValueTy = num_bigint::BigUint; |
| const TAG: yasna::Tag = yasna::tags::TAG_INTEGER; |
| fn dump<'a>(writer: Writer<'a>, value: Self::ValueTy) { |
| writer.write_biguint(&value); |
| } |
| fn load<'a, 'b>(reader: Reader<'a, 'b>) -> ASN1Result<Self::ValueTy> |
| where |
| 'a: 'b, |
| { |
| reader.read_biguint() |
| } |
| } |
| |
| impl Asn1Ty for Utf8Str { |
| type ValueTy = String; |
| const TAG: yasna::Tag = yasna::tags::TAG_UTF8STRING; |
| fn dump<'a>(writer: Writer<'a>, value: Self::ValueTy) { |
| writer.write_utf8_string(value.as_str()); |
| } |
| fn load<'a, 'b>(reader: Reader<'a, 'b>) -> ASN1Result<Self::ValueTy> |
| where |
| 'a: 'b, |
| { |
| reader.read_utf8string() |
| } |
| } |
| |
| impl Asn1Ty for Oid { |
| type ValueTy = yasna::models::ObjectIdentifier; |
| const TAG: yasna::Tag = yasna::tags::TAG_OID; |
| fn dump<'a>(writer: Writer<'a>, value: Self::ValueTy) { |
| writer.write_oid(&value); |
| } |
| fn load<'a, 'b>(reader: Reader<'a, 'b>) -> ASN1Result<Self::ValueTy> |
| where |
| 'a: 'b, |
| { |
| reader.read_oid() |
| } |
| } |
| |
| impl Asn1Ty for UtcTime { |
| type ValueTy = yasna::models::UTCTime; |
| const TAG: yasna::Tag = yasna::tags::TAG_UTCTIME; |
| fn dump<'a>(writer: Writer<'a>, value: Self::ValueTy) { |
| writer.write_utctime(&value); |
| } |
| fn load<'a, 'b>(reader: Reader<'a, 'b>) -> ASN1Result<Self::ValueTy> |
| where |
| 'a: 'b, |
| { |
| reader.read_utctime() |
| } |
| } |
| |
| impl Asn1Ty for BitVec { |
| type ValueTy = bit_vec::BitVec; |
| const TAG: yasna::Tag = yasna::tags::TAG_BITSTRING; |
| fn dump<'a>(writer: Writer<'a>, value: Self::ValueTy) { |
| writer.write_bitvec(&value); |
| } |
| fn load<'a, 'b>(reader: Reader<'a, 'b>) -> ASN1Result<Self::ValueTy> |
| where |
| 'a: 'b, |
| { |
| reader.read_bitvec() |
| } |
| } |
| |
| impl Asn1Ty for Bytes { |
| type ValueTy = Vec<u8>; |
| const TAG: yasna::Tag = yasna::tags::TAG_OCTETSTRING; |
| fn dump<'a>(writer: Writer<'a>, value: Self::ValueTy) { |
| writer.write_bytes(&value.as_slice()); |
| } |
| fn load<'a, 'b>(reader: Reader<'a, 'b>) -> ASN1Result<Self::ValueTy> |
| where |
| 'a: 'b, |
| { |
| reader.read_bytes() |
| } |
| } |
| |
| macro_rules! cons { |
| () => { Nil }; |
| ($t: ty) => { Cons<$t, Nil> }; |
| ($t: ty, $($tt: ty),* $(,)?) => { |
| Cons<$t, cons! { $($tt),* }> |
| }; |
| } |
| |
| macro_rules! asn1_seq_ty { |
| ($t: ty) => { Sequence<$t, Nil> }; |
| ($t: ty, $($tt: ty),* $(,)?) => { |
| Sequence<$t, cons! { $($tt),* }> |
| }; |
| } |
| |
| macro_rules! asn1_set_ty { |
| ($t: ty) => { Set<$t, Nil> }; |
| ($t: ty, $($tt: ty),* $(,)?) => { |
| Set<$t, cons! { $($tt),* }> |
| }; |
| } |
| |
| #[cfg(feature = "mesalock_sgx")] |
| macro_rules! asn1_seq { |
| () => { () }; |
| ($e: expr) => { |
| ($e, ()) |
| }; |
| ($e: expr , $($ee: expr),* $(,)?) => { |
| ($e, asn1_seq!{ $($ee),* } ) |
| }; |
| } |
| |
| pub(crate) type Version = Tagged<CtxT0, I8>; |
| pub(crate) type Serial = U8; |
| pub(crate) type CertSignAlgo = asn1_seq_ty!(Oid); |
| pub(crate) type ValidRange = asn1_seq_ty!(UtcTime, UtcTime); |
| pub(crate) type Issuer = asn1_seq_ty!(asn1_set_ty!(asn1_seq_ty!(Oid, Utf8Str))); |
| pub(crate) type Subject = Issuer; |
| pub(crate) type PubKeyAlgo = asn1_seq_ty!(Oid, Oid); |
| pub(crate) type PubKey = asn1_seq_ty!(PubKeyAlgo, BitVec); |
| pub(crate) type SgxRaCertExt = Tagged<CtxT3, asn1_seq_ty!(asn1_seq_ty!(Oid, Bytes))>; |
| pub(crate) type TbsCert = asn1_seq_ty!( |
| Version, |
| Serial, |
| CertSignAlgo, |
| Issuer, |
| ValidRange, |
| Subject, |
| PubKey, |
| SgxRaCertExt, |
| ); |
| pub(crate) type CertSig = BitVec; |
| pub(crate) type X509 = asn1_seq_ty!(TbsCert, CertSignAlgo, CertSig); |