migrated some core components to core crate

This commit is contained in:
sinuio
2022-06-03 18:45:41 -07:00
parent 7d4caa63e2
commit 0ed5dc18ef
101 changed files with 702 additions and 350 deletions

View File

@@ -24,6 +24,7 @@ ring = "0.16.20"
sct = "0.7.0"
tokio = { version = "1.18.2", features = ["macros", "rt", "rt-multi-thread"] }
webpki = { version = "0.22.0", features = ["alloc", "std"] }
tlsn-tls-core = { path = "../tls-core" }
[features]
default = ["logging", "tls12"]

View File

@@ -1,8 +1,8 @@
use crate::key;
#[cfg(feature = "logging")]
use crate::log::{debug, trace};
use crate::msgs::handshake::{DistinguishedName, DistinguishedNames};
use crate::x509;
use tls_core::key;
use tls_core::msgs::handshake::{DistinguishedName, DistinguishedNames};
/// A trust anchor, commonly known as a "Root Certificate."
#[derive(Debug, Clone)]
@@ -82,7 +82,7 @@ impl RootCertStore {
}
/// Add a single DER-encoded certificate to the store.
pub fn add(&mut self, der: &key::Certificate) -> Result<(), webpki::Error> {
pub fn add(&mut self, der: &tls_core::key::Certificate) -> Result<(), webpki::Error> {
let ta = webpki::TrustAnchor::try_from_cert_der(&der.0)?;
let ota = OwnedTrustAnchor::from_subject_spki_name_constraints(
ta.subject,
@@ -115,7 +115,7 @@ impl RootCertStore {
for der_cert in der_certs {
#[cfg_attr(not(feature = "logging"), allow(unused_variables))]
match self.add(&key::Certificate(der_cert.clone())) {
match self.add(&tls_core::key::Certificate(der_cert.clone())) {
Ok(_) => valid_count += 1,
Err(err) => {
trace!("invalid cert der {:?}", der_cert);

View File

@@ -1,8 +1,8 @@
use crate::error::Error;
#[cfg(feature = "logging")]
use crate::log::warn;
use crate::msgs::enums::{ContentType, HandshakeType};
use crate::msgs::message::MessagePayload;
use tls_core::msgs::enums::{ContentType, HandshakeType};
use tls_core::msgs::message::MessagePayload;
/// For a Message $m, and a HandshakePayload enum member $payload_type,
/// return Ok(payload) if $m is both a handshake message and one that
@@ -11,13 +11,13 @@ use crate::msgs::message::MessagePayload;
macro_rules! require_handshake_msg(
( $m:expr, $handshake_type:path, $payload_type:path ) => (
match &$m.payload {
MessagePayload::Handshake($crate::msgs::handshake::HandshakeMessagePayload {
MessagePayload::Handshake($crate::tls_core::msgs::handshake::HandshakeMessagePayload {
payload: $payload_type(hm),
..
}) => Ok(hm),
payload => Err($crate::check::inappropriate_handshake_message(
payload,
&[$crate::msgs::enums::ContentType::Handshake],
&[$crate::tls_core::msgs::enums::ContentType::Handshake],
&[$handshake_type]))
}
)
@@ -28,14 +28,14 @@ macro_rules! require_handshake_msg(
macro_rules! require_handshake_msg_move(
( $m:expr, $handshake_type:path, $payload_type:path ) => (
match $m.payload {
MessagePayload::Handshake($crate::msgs::handshake::HandshakeMessagePayload {
MessagePayload::Handshake($crate::tls_core::msgs::handshake::HandshakeMessagePayload {
payload: $payload_type(hm),
..
}) => Ok(hm),
payload =>
Err($crate::check::inappropriate_handshake_message(
&payload,
&[$crate::msgs::enums::ContentType::Handshake],
&[$crate::tls_core::msgs::enums::ContentType::Handshake],
&[$handshake_type]))
}
)

View File

@@ -1,6 +1,6 @@
use crate::error::Error;
use crate::msgs::codec;
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
use tls_core::msgs::codec;
use tls_core::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
use async_trait::async_trait;
use ring::{aead, hkdf};

View File

@@ -3,12 +3,12 @@ use crate::builder::{ConfigBuilder, WantsVerifier};
use crate::client::handy;
use crate::client::{ClientConfig, ResolvesClientCert};
use crate::error::Error;
use crate::key;
use crate::kx::SupportedKxGroup;
use crate::suites::SupportedCipherSuite;
use crate::verify::{self, CertificateTransparencyPolicy};
use crate::versions;
use crate::NoKeyLog;
use tls_core::key;
use std::sync::Arc;
use std::time::SystemTime;
@@ -88,7 +88,7 @@ impl ConfigBuilder<WantsTransparencyPolicyOrClientCert> {
/// This function fails if `key_der` is invalid.
pub fn with_single_cert(
self,
cert_chain: Vec<key::Certificate>,
cert_chain: Vec<tls_core::key::Certificate>,
key_der: key::PrivateKey,
) -> Result<ClientConfig, Error> {
self.with_logs(None).with_single_cert(cert_chain, key_der)
@@ -148,7 +148,7 @@ impl ConfigBuilder<WantsClientCert> {
/// This function fails if `key_der` is invalid.
pub fn with_single_cert(
self,
cert_chain: Vec<key::Certificate>,
cert_chain: Vec<tls_core::key::Certificate>,
key_der: key::PrivateKey,
) -> Result<ClientConfig, Error> {
let resolver = handy::AlwaysResolvesClientCert::new(cert_chain, &key_der)?;

View File

@@ -6,16 +6,16 @@ use crate::error::Error;
use crate::kx::SupportedKxGroup;
#[cfg(feature = "logging")]
use crate::log::trace;
use crate::msgs::enums::CipherSuite;
use crate::msgs::enums::ProtocolVersion;
use crate::msgs::enums::SignatureScheme;
use crate::msgs::handshake::ClientExtension;
use crate::msgs::message::Message;
use crate::sign;
use crate::suites::SupportedCipherSuite;
use crate::verify;
use crate::versions;
use crate::KeyLog;
use tls_core::msgs::enums::CipherSuite;
use tls_core::msgs::enums::ProtocolVersion;
use tls_core::msgs::enums::SignatureScheme;
use tls_core::msgs::handshake::ClientExtension;
use tls_core::msgs::message::Message;
use super::hs;
@@ -375,20 +375,23 @@ pub struct Initialized {
server_name: ServerName,
extra_exts: Vec<ClientExtension>,
proto: Protocol,
config: Arc<ClientConfig>
config: Arc<ClientConfig>,
}
#[async_trait]
impl State<ClientConnectionData> for Initialized {
async fn start(self: Box<Self>, cx: &mut crate::conn::Context<'_>) -> Result<Box<dyn State<ClientConnectionData>>, Error> {
async fn start(
self: Box<Self>,
cx: &mut crate::conn::Context<'_>,
) -> Result<Box<dyn State<ClientConnectionData>>, Error> {
hs::start_handshake(self.server_name, self.extra_exts, self.config, cx).await
}
async fn handle(
self: Box<Self>,
_cx: &mut crate::conn::Context<'_>,
_message: Message
) -> Result<Box<dyn State<ClientConnectionData> > ,Error> {
_message: Message,
) -> Result<Box<dyn State<ClientConnectionData>>, Error> {
unreachable!()
}
}
@@ -426,7 +429,7 @@ impl ClientConnection {
server_name: name,
extra_exts,
proto,
config
config,
});
let inner = ConnectionCommon::new(state, data, common_state);

View File

@@ -1,11 +1,11 @@
use super::ResolvesClientCert;
#[cfg(feature = "logging")]
use crate::log::{debug, trace};
use crate::msgs::enums::ExtensionType;
use crate::msgs::handshake::CertificatePayload;
use crate::msgs::handshake::SCTList;
use crate::msgs::handshake::ServerExtension;
use crate::{sign, DistinguishedNames, SignatureScheme};
use tls_core::msgs::enums::ExtensionType;
use tls_core::msgs::handshake::CertificatePayload;
use tls_core::msgs::handshake::SCTList;
use tls_core::msgs::handshake::ServerExtension;
use std::sync::Arc;
@@ -49,8 +49,7 @@ impl ClientHelloDetails {
}
pub(super) fn server_may_send_sct_list(&self) -> bool {
self.sent_extensions
.contains(&ExtensionType::SCT)
self.sent_extensions.contains(&ExtensionType::SCT)
}
pub(super) fn server_sent_unsolicited_extensions(

View File

@@ -1,9 +1,9 @@
use crate::client;
use crate::error::Error;
use crate::key;
use crate::limited_cache;
use crate::msgs::enums::SignatureScheme;
use crate::sign;
use tls_core::key;
use tls_core::msgs::enums::SignatureScheme;
use std::sync::{Arc, Mutex};
@@ -40,19 +40,12 @@ impl ClientSessionMemoryCache {
impl client::StoresClientSessions for ClientSessionMemoryCache {
fn put(&self, key: Vec<u8>, value: Vec<u8>) -> bool {
self.cache
.lock()
.unwrap()
.insert(key, value);
self.cache.lock().unwrap().insert(key, value);
true
}
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
self.cache
.lock()
.unwrap()
.get(key)
.cloned()
self.cache.lock().unwrap().get(key).cloned()
}
}
@@ -76,7 +69,7 @@ pub(super) struct AlwaysResolvesClientCert(Arc<sign::CertifiedKey>);
impl AlwaysResolvesClientCert {
pub(super) fn new(
chain: Vec<key::Certificate>,
chain: Vec<tls_core::key::Certificate>,
priv_key: &key::PrivateKey,
) -> Result<Self, Error> {
let key = sign::any_supported_type(priv_key)

View File

@@ -7,25 +7,25 @@ use crate::hash_hs::HandshakeHashBuffer;
use crate::kx;
#[cfg(feature = "logging")]
use crate::log::{debug, trace};
use crate::msgs::base::Payload;
use crate::msgs::codec::{Codec, Reader};
use crate::msgs::enums::{
AlertDescription, CipherSuite, Compression, ContentType, ProtocolVersion,
};
use crate::msgs::enums::{ECPointFormat, PSKKeyExchangeMode};
use crate::msgs::enums::{ExtensionType, HandshakeType};
use crate::msgs::handshake::{CertificateStatusRequest, ClientSessionTicket, SCTList};
use crate::msgs::handshake::{ClientExtension, HasServerExtensions};
use crate::msgs::handshake::{ClientHelloPayload, HandshakeMessagePayload, HandshakePayload};
use crate::msgs::handshake::{ConvertProtocolNameList, ProtocolNameList};
use crate::msgs::handshake::{ECPointFormatList, SupportedPointFormats};
use crate::msgs::handshake::{HelloRetryRequest, KeyShareEntry};
use crate::msgs::handshake::{Random, SessionID};
use crate::msgs::message::{Message, MessagePayload};
use crate::msgs::persist;
use crate::ticketer::TimeBase;
use crate::tls13::key_schedule::KeyScheduleEarly;
use crate::SupportedCipherSuite;
use tls_core::msgs::base::Payload;
use tls_core::msgs::codec::{Codec, Reader};
use tls_core::msgs::enums::{
AlertDescription, CipherSuite, Compression, ContentType, ProtocolVersion,
};
use tls_core::msgs::enums::{ECPointFormat, PSKKeyExchangeMode};
use tls_core::msgs::enums::{ExtensionType, HandshakeType};
use tls_core::msgs::handshake::{CertificateStatusRequest, ClientSessionTicket, SCTList};
use tls_core::msgs::handshake::{ClientExtension, HasServerExtensions};
use tls_core::msgs::handshake::{ClientHelloPayload, HandshakeMessagePayload, HandshakePayload};
use tls_core::msgs::handshake::{ConvertProtocolNameList, ProtocolNameList};
use tls_core::msgs::handshake::{ECPointFormatList, SupportedPointFormats};
use tls_core::msgs::handshake::{HelloRetryRequest, KeyShareEntry};
use tls_core::msgs::handshake::{Random, SessionID};
use tls_core::msgs::message::{Message, MessagePayload};
#[cfg(feature = "tls12")]
use super::tls12;

View File

@@ -4,21 +4,25 @@ use crate::error::Error;
use crate::hash_hs::HandshakeHash;
#[cfg(feature = "logging")]
use crate::log::{debug, trace};
use crate::msgs::base::{Payload, PayloadU8};
use crate::msgs::ccs::ChangeCipherSpecPayload;
use crate::msgs::codec::Codec;
use crate::msgs::enums::{AlertDescription, ProtocolVersion};
use crate::msgs::enums::{ContentType, HandshakeType};
use crate::msgs::handshake::{CertificatePayload, DecomposedSignatureScheme, SCTList, SessionID};
use crate::msgs::handshake::{DigitallySignedStruct, ServerECDHParams};
use crate::msgs::handshake::{HandshakeMessagePayload, HandshakePayload, NewSessionTicketPayload};
use crate::msgs::message::{Message, MessagePayload};
use crate::msgs::persist;
use crate::sign::Signer;
use crate::suites::SupportedCipherSuite;
use crate::ticketer::TimeBase;
use crate::tls12::{self, ConnectionSecrets, Tls12CipherSuite};
use crate::{kx, verify};
use tls_core::msgs::base::{Payload, PayloadU8};
use tls_core::msgs::ccs::ChangeCipherSpecPayload;
use tls_core::msgs::codec::Codec;
use tls_core::msgs::enums::{AlertDescription, ProtocolVersion};
use tls_core::msgs::enums::{ContentType, HandshakeType};
use tls_core::msgs::handshake::{
CertificatePayload, DecomposedSignatureScheme, SCTList, SessionID,
};
use tls_core::msgs::handshake::{DigitallySignedStruct, ServerECDHParams};
use tls_core::msgs::handshake::{
HandshakeMessagePayload, HandshakePayload, NewSessionTicketPayload,
};
use tls_core::msgs::message::{Message, MessagePayload};
use super::client_conn::ClientConnectionData;
use super::hs::ClientContext;
@@ -35,9 +39,9 @@ use std::sync::Arc;
pub(super) use server_hello::CompleteServerHelloHandling;
mod server_hello {
use crate::msgs::enums::ExtensionType;
use crate::msgs::handshake::HasServerExtensions;
use crate::msgs::handshake::ServerHelloPayload;
use tls_core::msgs::enums::ExtensionType;
use tls_core::msgs::handshake::HasServerExtensions;
use tls_core::msgs::handshake::ServerHelloPayload;
use super::*;

View File

@@ -5,21 +5,6 @@ use crate::hash_hs::{HandshakeHash, HandshakeHashBuffer};
use crate::kx;
#[cfg(feature = "logging")]
use crate::log::{debug, trace, warn};
use crate::msgs::base::{Payload, PayloadU8};
use crate::msgs::ccs::ChangeCipherSpecPayload;
use crate::msgs::codec::Codec;
use crate::msgs::enums::KeyUpdateRequest;
use crate::msgs::enums::{AlertDescription, NamedGroup, ProtocolVersion};
use crate::msgs::enums::{ContentType, ExtensionType, HandshakeType, SignatureScheme};
use crate::msgs::handshake::ClientExtension;
use crate::msgs::handshake::DigitallySignedStruct;
use crate::msgs::handshake::EncryptedExtensions;
use crate::msgs::handshake::NewSessionTicketPayloadTLS13;
use crate::msgs::handshake::{CertificateEntry, CertificatePayloadTLS13};
use crate::msgs::handshake::{HandshakeMessagePayload, HandshakePayload};
use crate::msgs::handshake::{HasServerExtensions, ServerHelloPayload};
use crate::msgs::handshake::{PresharedKeyIdentity, PresharedKeyOffer};
use crate::msgs::message::{Message, MessagePayload};
use crate::msgs::persist;
use crate::tls13::key_schedule::{
KeyScheduleEarly, KeyScheduleHandshake, KeySchedulePreHandshake, KeyScheduleTraffic,
@@ -27,6 +12,21 @@ use crate::tls13::key_schedule::{
use crate::tls13::Tls13CipherSuite;
use crate::verify;
use crate::{sign, KeyLog};
use tls_core::msgs::base::{Payload, PayloadU8};
use tls_core::msgs::ccs::ChangeCipherSpecPayload;
use tls_core::msgs::codec::Codec;
use tls_core::msgs::enums::KeyUpdateRequest;
use tls_core::msgs::enums::{AlertDescription, NamedGroup, ProtocolVersion};
use tls_core::msgs::enums::{ContentType, ExtensionType, HandshakeType, SignatureScheme};
use tls_core::msgs::handshake::ClientExtension;
use tls_core::msgs::handshake::DigitallySignedStruct;
use tls_core::msgs::handshake::EncryptedExtensions;
use tls_core::msgs::handshake::NewSessionTicketPayloadTLS13;
use tls_core::msgs::handshake::{CertificateEntry, CertificatePayloadTLS13};
use tls_core::msgs::handshake::{HandshakeMessagePayload, HandshakePayload};
use tls_core::msgs::handshake::{HasServerExtensions, ServerHelloPayload};
use tls_core::msgs::handshake::{PresharedKeyIdentity, PresharedKeyOffer};
use tls_core::msgs::message::{Message, MessagePayload};
use super::client_conn::ClientConnectionData;
use super::hs::ClientContext;

View File

@@ -2,23 +2,23 @@ use crate::client::ClientConnectionData;
use crate::error::Error;
#[cfg(feature = "logging")]
use crate::log::{debug, error, trace, warn};
use crate::msgs::alert::AlertMessagePayload;
use crate::msgs::base::Payload;
use crate::msgs::deframer::MessageDeframer;
use crate::msgs::enums::HandshakeType;
use crate::msgs::enums::{AlertDescription, AlertLevel, ContentType, ProtocolVersion};
use crate::msgs::fragmenter::MessageFragmenter;
use crate::msgs::handshake::Random;
use crate::msgs::hsjoiner::HandshakeJoiner;
use crate::msgs::message::{
BorrowedPlainMessage, Message, MessagePayload, OpaqueMessage, PlainMessage,
};
use crate::record_layer;
use crate::suites::SupportedCipherSuite;
#[cfg(feature = "tls12")]
use crate::tls12::ConnectionSecrets;
use crate::vecbuf::ChunkVecBuffer;
use crate::{handshaker, key};
use tls_core::msgs::alert::AlertMessagePayload;
use tls_core::msgs::base::Payload;
use tls_core::msgs::deframer::MessageDeframer;
use tls_core::msgs::enums::HandshakeType;
use tls_core::msgs::enums::{AlertDescription, AlertLevel, ContentType, ProtocolVersion};
use tls_core::msgs::fragmenter::MessageFragmenter;
use tls_core::msgs::handshake::Random;
use tls_core::msgs::hsjoiner::HandshakeJoiner;
use tls_core::msgs::message::{
BorrowedPlainMessage, Message, MessagePayload, OpaqueMessage, PlainMessage,
};
use async_recursion::async_recursion;
use async_trait::async_trait;
@@ -588,7 +588,7 @@ pub struct CommonState {
has_received_close_notify: bool,
has_seen_eof: bool,
received_middlebox_ccs: u8,
pub(crate) peer_certificates: Option<Vec<key::Certificate>>,
pub(crate) peer_certificates: Option<Vec<tls_core::key::Certificate>>,
message_fragmenter: MessageFragmenter,
received_plaintext: ChunkVecBuffer,
sendable_plaintext: ChunkVecBuffer,
@@ -656,7 +656,7 @@ impl CommonState {
/// if client authentication was completed.
///
/// The return value is None until this value is available.
pub fn peer_certificates(&self) -> Option<&[key::Certificate]> {
pub fn peer_certificates(&self) -> Option<&[tls_core::key::Certificate]> {
self.peer_certificates.as_deref()
}
@@ -1041,7 +1041,9 @@ impl CommonState {
}
pub(crate) fn set_max_fragment_size(&mut self, new: Option<usize>) -> Result<(), Error> {
self.message_fragmenter.set_max_fragment_size(new)
self.message_fragmenter
.set_max_fragment_size(new)
.map_err(|e| Error::from(e))
}
pub(crate) fn get_alpn_protocol(&self) -> Option<&[u8]> {

View File

@@ -1,5 +1,6 @@
use crate::msgs::enums::{AlertDescription, ContentType, HandshakeType};
use crate::rand;
use tls_core::msgs::enums::{AlertDescription, ContentType, HandshakeType};
use tls_core::Error as CoreError;
use std::error::Error as StdError;
use std::fmt;
@@ -8,6 +9,9 @@ use std::time::SystemTimeError;
/// rustls reports protocol errors using this type.
#[derive(Debug, PartialEq, Clone)]
pub enum Error {
/// Error propagated from Core component
CoreError(CoreError),
/// We received a TLS message that isn't valid right now.
/// `expect_types` lists the message types we can expect right now.
/// `got_type` is the type we found. This error is typically
@@ -110,6 +114,9 @@ fn join<T: fmt::Debug>(items: &[T]) -> String {
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::CoreError(ref e) => {
write!(f, "core error: {}", e)
}
Error::InappropriateMessage {
ref expect_types,
ref got_type,
@@ -165,6 +172,13 @@ impl fmt::Display for Error {
}
}
impl From<CoreError> for Error {
#[inline]
fn from(e: CoreError) -> Self {
Self::CoreError(e)
}
}
impl From<SystemTimeError> for Error {
#[inline]
fn from(_: SystemTimeError) -> Self {
@@ -186,8 +200,8 @@ mod tests {
#[test]
fn smoke() {
use crate::msgs::enums::{AlertDescription, ContentType, HandshakeType};
use sct;
use tls_core::msgs::enums::{AlertDescription, ContentType, HandshakeType};
let all = vec![
Error::InappropriateMessage {

View File

@@ -1,7 +1,7 @@
use std::ops::{Deref, DerefMut};
use crate::kx::KeyExchange;
use crate::msgs::handshake::Random;
use tls_core::msgs::handshake::Random;
use crate::Error;
use async_trait::async_trait;

View File

@@ -1,6 +1,6 @@
use crate::msgs::codec::Codec;
use crate::msgs::handshake::HandshakeMessagePayload;
use crate::msgs::message::{Message, MessagePayload};
use tls_core::msgs::codec::Codec;
use tls_core::msgs::handshake::HandshakeMessagePayload;
use tls_core::msgs::message::{Message, MessagePayload};
use ring::digest;
use std::mem;

View File

@@ -28,11 +28,7 @@ impl KeyLogFileInner {
};
#[cfg_attr(not(feature = "logging"), allow(unused_variables))]
let file = match OpenOptions::new()
.append(true)
.create(true)
.open(path)
{
let file = match OpenOptions::new().append(true).create(true).open(path) {
Ok(f) => Some(f),
Err(e) => {
warn!("unable to create key log file {:?}: {}", path, e);
@@ -109,9 +105,7 @@ mod test {
use super::*;
fn init() {
let _ = env_logger::builder()
.is_test(true)
.try_init();
let _ = env_logger::builder().is_test(true).try_init();
}
#[test]
@@ -120,35 +114,27 @@ mod test {
let mut inner = KeyLogFileInner::new(Err(env::VarError::NotUnicode(
"/tmp/keylogfileinnertest".into(),
)));
assert!(inner
.try_write("label", b"random", b"secret")
.is_ok());
assert!(inner.try_write("label", b"random", b"secret").is_ok());
}
#[test]
fn test_env_var_is_not_set() {
init();
let mut inner = KeyLogFileInner::new(Err(env::VarError::NotPresent));
assert!(inner
.try_write("label", b"random", b"secret")
.is_ok());
assert!(inner.try_write("label", b"random", b"secret").is_ok());
}
#[test]
fn test_env_var_cannot_be_opened() {
init();
let mut inner = KeyLogFileInner::new(Ok("/dev/does-not-exist".into()));
assert!(inner
.try_write("label", b"random", b"secret")
.is_ok());
assert!(inner.try_write("label", b"random", b"secret").is_ok());
}
#[test]
fn test_env_var_cannot_be_written() {
init();
let mut inner = KeyLogFileInner::new(Ok("/dev/full".into()));
assert!(inner
.try_write("label", b"random", b"secret")
.is_err());
assert!(inner.try_write("label", b"random", b"secret").is_err());
}
}

View File

@@ -1,5 +1,5 @@
use crate::error::Error;
use crate::msgs::enums::NamedGroup;
use tls_core::msgs::enums::NamedGroup;
/// An in-progress key exchange. This has the algorithm,
/// our private key, and our public key.

View File

@@ -308,18 +308,19 @@ mod log {
macro_rules! error ( ($($tt:tt)*) => {{}} );
}
#[allow(missing_docs)]
#[macro_use]
mod msgs;
pub extern crate tls_core;
mod anchors;
mod cipher;
mod conn;
mod error;
mod handshaker;
mod hash_hs;
mod limited_cache;
mod msgs;
mod rand;
mod record_layer;
mod handshaker;
//mod stream;
#[cfg(feature = "tls12")]
mod tls12;
@@ -346,7 +347,7 @@ mod versions;
pub mod internal {
/// Low-level TLS message parsing and encoding functions.
pub mod msgs {
pub use crate::msgs::*;
pub use tls_core::msgs::*;
}
/// Low-level TLS message decryption functions.
pub mod cipher {
@@ -361,14 +362,14 @@ pub use crate::builder::{
};
pub use crate::conn::{CommonState, ConnectionCommon, IoState, Reader, SideData};
pub use crate::error::Error;
pub use crate::key::{Certificate, PrivateKey};
pub use crate::key_log::{KeyLog, NoKeyLog};
pub use crate::key_log_file::KeyLogFile;
pub use crate::kx::{SupportedKxGroup, ALL_KX_GROUPS};
pub use crate::msgs::enums::CipherSuite;
pub use crate::msgs::enums::ProtocolVersion;
pub use crate::msgs::enums::SignatureScheme;
pub use crate::msgs::handshake::DistinguishedNames;
pub use tls_core::key::{Certificate, PrivateKey};
pub use tls_core::msgs::enums::CipherSuite;
pub use tls_core::msgs::enums::ProtocolVersion;
pub use tls_core::msgs::enums::SignatureScheme;
pub use tls_core::msgs::handshake::DistinguishedNames;
//pub use crate::stream::{Stream, StreamOwned};
pub use crate::suites::{
BulkAlgorithm, SupportedCipherSuite, ALL_CIPHER_SUITES, DEFAULT_CIPHER_SUITES,

View File

@@ -1,52 +1,4 @@
#![allow(clippy::upper_case_acronyms)]
#[macro_use]
mod macros;
pub mod alert;
pub mod base;
pub mod ccs;
pub mod codec;
pub mod deframer;
#[allow(non_camel_case_types)]
pub mod enums;
pub mod fragmenter;
#[allow(non_camel_case_types)]
pub mod handshake;
pub mod hsjoiner;
pub mod message;
pub mod persist;
#[cfg(test)]
mod handshake_test;
pub(crate) mod persist;
#[cfg(test)]
mod persist_test;
#[cfg(test)]
mod enums_test;
#[cfg(test)]
mod message_test;
#[cfg(test)]
mod test {
use std::convert::TryFrom;
#[test]
fn smoketest() {
use super::codec::Reader;
use super::message::{Message, OpaqueMessage};
let bytes = include_bytes!("handshake-test.1.bin");
let mut r = Reader::init(bytes);
while r.any_left() {
let m = OpaqueMessage::read(&mut r).unwrap();
let out = m.clone().encode();
assert!(!out.is_empty());
Message::try_from(m.into_plain_message()).unwrap();
}
}
}

View File

@@ -1,15 +1,15 @@
use crate::client::ServerName;
use crate::key;
use crate::msgs::base::{PayloadU16, PayloadU8};
use crate::msgs::codec::{Codec, Reader};
use crate::msgs::enums::{CipherSuite, ProtocolVersion};
use crate::msgs::handshake::CertificatePayload;
use crate::msgs::handshake::SessionID;
use crate::suites::SupportedCipherSuite;
use crate::ticketer::TimeBase;
#[cfg(feature = "tls12")]
use crate::tls12::Tls12CipherSuite;
use crate::tls13::Tls13CipherSuite;
use tls_core::key;
use tls_core::msgs::base::{PayloadU16, PayloadU8};
use tls_core::msgs::codec::{Codec, Reader};
use tls_core::msgs::enums::{CipherSuite, ProtocolVersion};
use tls_core::msgs::handshake::CertificatePayload;
use tls_core::msgs::handshake::SessionID;
use std::cmp;
#[cfg(feature = "tls12")]
@@ -67,10 +67,7 @@ impl ClientSessionValue {
suite: CipherSuite,
supported: &[SupportedCipherSuite],
) -> Option<Self> {
match supported
.iter()
.find(|s| s.suite() == suite)?
{
match supported.iter().find(|s| s.suite() == suite)? {
SupportedCipherSuite::Tls13(inner) => {
Tls13ClientSessionValue::read(inner, reader).map(ClientSessionValue::Tls13)
}
@@ -165,7 +162,7 @@ impl Tls13ClientSessionValue {
suite: &'static Tls13CipherSuite,
ticket: Vec<u8>,
secret: Vec<u8>,
server_cert_chain: Vec<key::Certificate>,
server_cert_chain: Vec<tls_core::key::Certificate>,
time_now: TimeBase,
lifetime_secs: u32,
age_add: u32,
@@ -203,13 +200,9 @@ impl Tls13ClientSessionValue {
/// (See `read()` for why this is inherent here.)
pub fn get_encoding(&self) -> Vec<u8> {
let mut bytes = Vec::with_capacity(16);
self.suite
.common
.suite
.encode(&mut bytes);
self.suite.common.suite.encode(&mut bytes);
self.age_add.encode(&mut bytes);
self.max_early_data_size
.encode(&mut bytes);
self.max_early_data_size.encode(&mut bytes);
self.common.encode(&mut bytes);
bytes
}
@@ -247,7 +240,7 @@ impl Tls12ClientSessionValue {
session_id: SessionID,
ticket: Vec<u8>,
master_secret: Vec<u8>,
server_cert_chain: Vec<key::Certificate>,
server_cert_chain: Vec<tls_core::key::Certificate>,
time_now: TimeBase,
lifetime_secs: u32,
extended_ms: bool,
@@ -284,10 +277,7 @@ impl Tls12ClientSessionValue {
/// (See `read()` for why this is inherent here.)
pub fn get_encoding(&self) -> Vec<u8> {
let mut bytes = Vec::with_capacity(16);
self.suite
.common
.suite
.encode(&mut bytes);
self.suite.common.suite.encode(&mut bytes);
self.session_id.encode(&mut bytes);
(if self.extended_ms { 1u8 } else { 0u8 }).encode(&mut bytes);
self.common.encode(&mut bytes);
@@ -331,7 +321,7 @@ impl ClientSessionCommon {
secret: Vec<u8>,
time_now: TimeBase,
lifetime_secs: u32,
server_cert_chain: Vec<key::Certificate>,
server_cert_chain: Vec<tls_core::key::Certificate>,
) -> Self {
Self {
ticket: PayloadU16(ticket),
@@ -366,7 +356,7 @@ impl ClientSessionCommon {
self.server_cert_chain.encode(bytes);
}
pub fn server_cert_chain(&self) -> &[key::Certificate] {
pub fn server_cert_chain(&self) -> &[tls_core::key::Certificate] {
self.server_cert_chain.as_ref()
}
@@ -437,8 +427,7 @@ impl Codec for ServerSessionValue {
}
self.application_data.encode(bytes);
self.creation_time_sec.encode(bytes);
self.age_obfuscation_offset
.encode(bytes);
self.age_obfuscation_offset.encode(bytes);
}
fn read(r: &mut Reader) -> Option<Self> {
@@ -519,10 +508,8 @@ impl ServerSessionValue {
pub fn set_freshness(mut self, obfuscated_client_age_ms: u32, time_now: TimeBase) -> Self {
let client_age_ms = obfuscated_client_age_ms.wrapping_sub(self.age_obfuscation_offset);
let server_age_ms = (time_now
.as_secs()
.saturating_sub(self.creation_time_sec) as u32)
.saturating_mul(1000);
let server_age_ms =
(time_now.as_secs().saturating_sub(self.creation_time_sec) as u32).saturating_mul(1000);
let age_difference = if client_age_ms < server_age_ms {
server_age_ms - client_age_ms

View File

@@ -1,10 +1,10 @@
use super::codec::{Codec, Reader};
use super::enums::*;
use super::persist::*;
use tls_core::msgs::codec::{Codec, Reader};
use tls_core::msgs::enums::*;
use crate::key::Certificate;
use crate::ticketer::TimeBase;
use crate::tls13::TLS13_AES_128_GCM_SHA256;
use tls_core::key::Certificate;
use std::convert::TryInto;
@@ -25,9 +25,7 @@ fn clientsessionkey_cannot_be_read() {
#[test]
fn clientsessionvalue_is_debug() {
let csv = ClientSessionValue::from(Tls13ClientSessionValue::new(
TLS13_AES_128_GCM_SHA256
.tls13()
.unwrap(),
TLS13_AES_128_GCM_SHA256.tls13().unwrap(),
vec![],
vec![1, 2, 3],
vec![Certificate(b"abc".to_vec()), Certificate(b"def".to_vec())],

View File

@@ -1,14 +1,12 @@
use crate::msgs::codec;
/// The single place where we generate random material
/// for our own use. These functions never fail,
/// they panic on error.
use ring::rand::{SecureRandom, SystemRandom};
use tls_core::msgs::codec;
/// Fill the whole slice with random material.
pub(crate) fn fill_random(bytes: &mut [u8]) -> Result<(), GetRandomFailed> {
SystemRandom::new()
.fill(bytes)
.map_err(|_| GetRandomFailed)
SystemRandom::new().fill(bytes).map_err(|_| GetRandomFailed)
}
/// Make a Vec<u8> of the given size

View File

@@ -1,6 +1,6 @@
use crate::cipher::{MessageDecrypter, MessageEncrypter};
use crate::error::Error;
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
use tls_core::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
static SEQ_SOFT_LIMIT: u64 = 0xffff_ffff_ffff_0000u64;
static SEQ_HARD_LIMIT: u64 = 0xffff_ffff_ffff_fffeu64;

View File

@@ -1,7 +1,7 @@
use crate::error::Error;
use crate::key;
use crate::msgs::enums::{SignatureAlgorithm, SignatureScheme};
use crate::x509::{wrap_in_asn1_len, wrap_in_sequence};
use tls_core::key;
use tls_core::msgs::enums::{SignatureAlgorithm, SignatureScheme};
use ring::io::der;
use ring::signature::{self, EcdsaKeyPair, Ed25519KeyPair, RsaKeyPair};
@@ -37,7 +37,7 @@ pub trait Signer: Send + Sync {
#[derive(Clone)]
pub struct CertifiedKey {
/// The certificate chain.
pub cert: Vec<key::Certificate>,
pub cert: Vec<tls_core::key::Certificate>,
/// The certified key.
pub key: Arc<dyn SigningKey>,
@@ -57,7 +57,7 @@ impl CertifiedKey {
///
/// The cert chain must not be empty. The first certificate in the chain
/// must be the end-entity certificate.
pub fn new(cert: Vec<key::Certificate>, key: Arc<dyn SigningKey>) -> Self {
pub fn new(cert: Vec<tls_core::key::Certificate>, key: Arc<dyn SigningKey>) -> Self {
Self {
cert,
key,
@@ -67,7 +67,7 @@ impl CertifiedKey {
}
/// The end-entity certificate.
pub fn end_entity_cert(&self) -> Result<&key::Certificate, SignError> {
pub fn end_entity_cert(&self) -> Result<&tls_core::key::Certificate, SignError> {
self.cert.get(0).ok_or(SignError(()))
}
@@ -84,11 +84,9 @@ impl CertifiedKey {
name: Option<webpki::DnsNameRef>,
) -> Result<(), Error> {
// Always reject an empty certificate chain.
let end_entity_cert = self
.end_entity_cert()
.map_err(|SignError(())| {
Error::General("No end-entity certificate in certificate chain".to_string())
})?;
let end_entity_cert = self.end_entity_cert().map_err(|SignError(())| {
Error::General("No end-entity certificate in certificate chain".to_string())
})?;
// Reject syntactically-invalid end-entity certificates.
let end_entity_cert =
@@ -106,10 +104,7 @@ impl CertifiedKey {
// certificate is valid; it only validates that the name is one
// that the certificate is valid for, if the certificate is
// valid.
if end_entity_cert
.verify_is_valid_for_dns_name(name)
.is_err()
{
if end_entity_cert.verify_is_valid_for_dns_name(name).is_err() {
return Err(Error::General(
"The server certificate is not \
valid for the given name"
@@ -354,7 +349,7 @@ impl SigningKey for EcdsaSigningKey {
}
fn algorithm(&self) -> SignatureAlgorithm {
use crate::msgs::handshake::DecomposedSignatureScheme;
use tls_core::msgs::handshake::DecomposedSignatureScheme;
self.scheme.sign()
}
}
@@ -420,7 +415,7 @@ impl SigningKey for Ed25519SigningKey {
}
fn algorithm(&self) -> SignatureAlgorithm {
use crate::msgs::handshake::DecomposedSignatureScheme;
use tls_core::msgs::handshake::DecomposedSignatureScheme;
self.scheme.sign()
}
}

View File

@@ -1,6 +1,6 @@
use crate::msgs::enums::ProtocolVersion;
use crate::msgs::enums::{CipherSuite, SignatureAlgorithm, SignatureScheme};
use crate::msgs::handshake::DecomposedSignatureScheme;
use tls_core::msgs::enums::ProtocolVersion;
use tls_core::msgs::enums::{CipherSuite, SignatureAlgorithm, SignatureScheme};
use tls_core::msgs::handshake::DecomposedSignatureScheme;
#[cfg(feature = "tls12")]
use crate::tls12::Tls12CipherSuite;
#[cfg(feature = "tls12")]
@@ -209,7 +209,7 @@ pub(crate) fn compatible_sigscheme_for_suites(
#[cfg(test)]
mod test {
use super::*;
use crate::msgs::enums::CipherSuite;
use tls_core::msgs::enums::CipherSuite;
#[test]
fn test_client_pref() {

View File

@@ -1,10 +1,10 @@
use crate::cipher::{make_nonce, Iv, MessageDecrypter, MessageEncrypter};
use crate::error::Error;
use crate::msgs::base::Payload;
use crate::msgs::codec;
use crate::msgs::enums::{ContentType, ProtocolVersion};
use crate::msgs::fragmenter::MAX_FRAGMENT_LEN;
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
use tls_core::msgs::base::Payload;
use tls_core::msgs::codec;
use tls_core::msgs::enums::{ContentType, ProtocolVersion};
use tls_core::msgs::fragmenter::MAX_FRAGMENT_LEN;
use tls_core::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
use async_trait::async_trait;
use ring::aead;

View File

@@ -1,10 +1,10 @@
use crate::cipher::{MessageDecrypter, MessageEncrypter};
use crate::conn::{CommonState, ConnectionRandoms, Side};
use crate::kx;
use crate::msgs::codec::{Codec, Reader};
use crate::msgs::enums::{AlertDescription, ContentType};
use crate::msgs::enums::{CipherSuite, SignatureScheme};
use crate::msgs::handshake::KeyExchangeAlgorithm;
use tls_core::msgs::codec::{Codec, Reader};
use tls_core::msgs::enums::{AlertDescription, ContentType};
use tls_core::msgs::enums::{CipherSuite, SignatureScheme};
use tls_core::msgs::handshake::KeyExchangeAlgorithm;
use crate::suites::{BulkAlgorithm, CipherSuiteCommon, SupportedCipherSuite};
use crate::Error;
@@ -438,7 +438,7 @@ pub(crate) const DOWNGRADE_SENTINEL: [u8; 8] = [0x44, 0x4f, 0x57, 0x4e, 0x47, 0x
#[cfg(test)]
mod tests {
use super::*;
use crate::msgs::handshake::{ClientECDHParams, ServerECDHParams};
use tls_core::msgs::handshake::{ClientECDHParams, ServerECDHParams};
#[test]
fn server_ecdhe_remaining_bytes() {

View File

@@ -1,7 +1,7 @@
use crate::cipher::{Iv, IvLen};
use crate::error::Error;
use crate::msgs::base::PayloadU8;
use crate::KeyLog;
use tls_core::msgs::base::{PayloadU8, PayloadU8Len};
/// Key schedule maintenance for TLS1.3
use ring::{
@@ -200,12 +200,8 @@ impl KeyScheduleHandshake {
) {
let traffic = KeyScheduleTraffic::new(self.ks, hs_hash, key_log, client_random);
let client_secret = traffic
.current_client_traffic_secret
.clone();
let server_secret = traffic
.current_server_traffic_secret
.clone();
let client_secret = traffic.current_client_traffic_secret.clone();
let server_secret = traffic.current_server_traffic_secret.clone();
let new = KeyScheduleTrafficWithClientFinishedPending {
handshake_client_traffic_secret: self.client_handshake_traffic_secret,
@@ -238,10 +234,7 @@ impl KeyScheduleTrafficWithClientFinishedPending {
.ks
.sign_finish(&self.handshake_client_traffic_secret, hs_hash);
let client_secret = self
.traffic
.current_client_traffic_secret
.clone();
let client_secret = self.traffic.current_client_traffic_secret.clone();
(self.traffic, tag, client_secret)
}
@@ -295,17 +288,13 @@ impl KeyScheduleTraffic {
}
pub(crate) fn next_server_application_traffic_secret(&mut self) -> hkdf::Prk {
let secret = self
.ks
.derive_next(&self.current_server_traffic_secret);
let secret = self.ks.derive_next(&self.current_server_traffic_secret);
self.current_server_traffic_secret = secret.clone();
secret
}
pub(crate) fn next_client_application_traffic_secret(&mut self) -> hkdf::Prk {
let secret = self
.ks
.derive_next(&self.current_client_traffic_secret);
let secret = self.ks.derive_next(&self.current_client_traffic_secret);
self.current_client_traffic_secret = secret.clone();
secret
}
@@ -320,8 +309,7 @@ impl KeyScheduleTraffic {
SecretKind::ResumptionMasterSecret,
hs_hash.as_ref(),
);
self.ks
.derive_ticket_psk(&resumption_master_secret, nonce)
self.ks.derive_ticket_psk(&resumption_master_secret, nonce)
}
pub(crate) fn export_keying_material(
@@ -383,9 +371,7 @@ impl KeySchedule {
key_log: &dyn KeyLog,
client_random: &[u8; 32],
) -> hkdf::Prk {
let log_label = kind
.log_label()
.expect("not a loggable secret");
let log_label = kind.log_label().expect("not a loggable secret");
if key_log.will_log(log_label) {
let secret = self
.derive::<PayloadU8, _>(PayloadU8Len(self.algorithm.len()), kind, hs_hash)
@@ -403,10 +389,7 @@ impl KeySchedule {
where
T: for<'a> From<hkdf::Okm<'a, hkdf::Algorithm>>,
{
let digest_alg = self
.algorithm
.hmac_algorithm()
.digest_algorithm();
let digest_alg = self.algorithm.hmac_algorithm().digest_algorithm();
let empty_hash = digest::digest(digest_alg, &[]);
self.derive(self.algorithm, kind, empty_hash.as_ref())
}
@@ -449,10 +432,7 @@ impl KeySchedule {
label: &[u8],
context: Option<&[u8]>,
) -> Result<(), Error> {
let digest_alg = self
.algorithm
.hmac_algorithm()
.digest_algorithm();
let digest_alg = self.algorithm.hmac_algorithm().digest_algorithm();
let h_empty = digest::digest(digest_alg, &[]);
let secret: hkdf::Prk = hkdf_expand(
@@ -514,21 +494,6 @@ where
f(okm)
}
pub(crate) struct PayloadU8Len(pub(crate) usize);
impl hkdf::KeyType for PayloadU8Len {
fn len(&self) -> usize {
self.0
}
}
impl From<hkdf::Okm<'_, PayloadU8Len>> for PayloadU8 {
fn from(okm: hkdf::Okm<PayloadU8Len>) -> Self {
let mut r = vec![0u8; okm.len().0];
okm.fill(&mut r[..]).unwrap();
Self::new(r)
}
}
pub(crate) fn derive_traffic_key(
secret: &hkdf::Prk,
aead_algorithm: &'static aead::Algorithm,

View File

@@ -1,11 +1,11 @@
use crate::cipher::{make_nonce, Iv, MessageDecrypter, MessageEncrypter};
use crate::error::Error;
use crate::msgs::base::Payload;
use crate::msgs::codec::Codec;
use crate::msgs::enums::{CipherSuite, ContentType, ProtocolVersion};
use crate::msgs::fragmenter::MAX_FRAGMENT_LEN;
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
use crate::suites::{BulkAlgorithm, CipherSuiteCommon, SupportedCipherSuite};
use tls_core::msgs::base::Payload;
use tls_core::msgs::codec::Codec;
use tls_core::msgs::enums::{CipherSuite, ContentType, ProtocolVersion};
use tls_core::msgs::fragmenter::MAX_FRAGMENT_LEN;
use tls_core::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
use ring::{aead, hkdf};

View File

@@ -1,11 +1,11 @@
use crate::anchors::{OwnedTrustAnchor, RootCertStore};
use crate::client::ServerName;
use crate::error::Error;
use crate::key::Certificate;
#[cfg(feature = "logging")]
use crate::log::{debug, trace, warn};
use crate::msgs::enums::SignatureScheme;
use crate::msgs::handshake::{DigitallySignedStruct, DistinguishedNames};
use tls_core::key::Certificate;
use tls_core::msgs::enums::SignatureScheme;
use tls_core::msgs::handshake::{DigitallySignedStruct, DistinguishedNames};
use ring::digest::Digest;
@@ -663,7 +663,7 @@ fn verify_signed_struct(
fn convert_alg_tls13(
scheme: SignatureScheme,
) -> Result<&'static webpki::SignatureAlgorithm, Error> {
use crate::msgs::enums::SignatureScheme::*;
use tls_core::msgs::enums::SignatureScheme::*;
match scheme {
ECDSA_NISTP256_SHA256 => Ok(&webpki::ECDSA_P256_SHA256),

View File

@@ -7,10 +7,10 @@
use std::convert::TryInto;
use std::time::{Duration, Instant, SystemTime};
use crate::key;
use crate::verify;
use crate::verify::ServerCertVerifier;
use crate::{anchors, OwnedTrustAnchor};
use tls_core::key;
use webpki_roots;
@@ -181,25 +181,20 @@ struct Context {
name: &'static str,
domain: &'static str,
roots: anchors::RootCertStore,
chain: Vec<key::Certificate>,
chain: Vec<tls_core::key::Certificate>,
now: SystemTime,
}
impl Context {
fn new(name: &'static str, domain: &'static str, certs: &[&'static [u8]]) -> Self {
let mut roots = anchors::RootCertStore::empty();
roots.add_server_trust_anchors(
webpki_roots::TLS_SERVER_ROOTS
.0
.iter()
.map(|ta| {
OwnedTrustAnchor::from_subject_spki_name_constraints(
ta.subject,
ta.spki,
ta.name_constraints,
)
}),
);
roots.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| {
OwnedTrustAnchor::from_subject_spki_name_constraints(
ta.subject,
ta.spki,
ta.name_constraints,
)
}));
Self {
name,
domain,
@@ -207,7 +202,7 @@ impl Context {
chain: certs
.iter()
.copied()
.map(|bytes| key::Certificate(bytes.to_vec()))
.map(|bytes| tls_core::key::Certificate(bytes.to_vec()))
.collect(),
now: SystemTime::UNIX_EPOCH + Duration::from_secs(1640870720),
}

View File

@@ -1,4 +1,4 @@
use crate::msgs::enums::ProtocolVersion;
use tls_core::msgs::enums::ProtocolVersion;
/// A TLS protocl version supported by rustls.
///

View File

@@ -8,9 +8,11 @@ name = "tls_core"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = ["handshake", "ghash"]
default = ["handshake", "ghash", "logging", "tls12"]
tls12 = []
handshake = []
ghash = []
logging = ["tracing"]
[dependencies]
tlsn-mpc-core = { path = "../mpc-core" }
@@ -19,6 +21,11 @@ digest = { version = "0.10.3" }
hmac = { version = "0.12.1" }
rand = "0.8.5"
thiserror = "1.0.30"
sct = "0.7.0"
webpki = { version = "0.22.0", features = ["alloc", "std"] }
tracing = { version = "0.1.34", optional = true }
# temporarily including ring
ring = "0.16.20"
[dev-dependencies]
criterion = "0.3.5"

231
tls-core/src/error.rs Normal file
View File

@@ -0,0 +1,231 @@
use crate::msgs::enums::{AlertDescription, ContentType, HandshakeType};
use std::error::Error as StdError;
use std::fmt;
use std::time::SystemTimeError;
/// rustls reports protocol errors using this type.
#[derive(Debug, PartialEq, Clone)]
pub enum Error {
/// We received a TLS message that isn't valid right now.
/// `expect_types` lists the message types we can expect right now.
/// `got_type` is the type we found. This error is typically
/// caused by a buggy TLS stack (the peer or this one), a broken
/// network, or an attack.
InappropriateMessage {
/// Which types we expected
expect_types: Vec<ContentType>,
/// What type we received
got_type: ContentType,
},
/// We received a TLS handshake message that isn't valid right now.
/// `expect_types` lists the handshake message types we can expect
/// right now. `got_type` is the type we found.
InappropriateHandshakeMessage {
/// Which handshake type we expected
expect_types: Vec<HandshakeType>,
/// What handshake type we received
got_type: HandshakeType,
},
/// The peer sent us a syntactically incorrect TLS message.
CorruptMessage,
/// The peer sent us a TLS message with invalid contents.
CorruptMessagePayload(ContentType),
/// The peer didn't give us any certificates.
NoCertificatesPresented,
/// The certificate verifier doesn't support the given type of name.
UnsupportedNameType,
/// We couldn't decrypt a message. This is invariably fatal.
DecryptError,
/// We couldn't encrypt a message because it was larger than the allowed message size.
/// This should never happen if the application is using valid record sizes.
EncryptError,
/// The peer doesn't support a protocol version/feature we require.
/// The parameter gives a hint as to what version/feature it is.
PeerIncompatibleError(String),
/// The peer deviated from the standard TLS protocol.
/// The parameter gives a hint where.
PeerMisbehavedError(String),
/// We received a fatal alert. This means the peer is unhappy.
AlertReceived(AlertDescription),
/// We received an invalidly encoded certificate from the peer.
InvalidCertificateEncoding,
/// We received a certificate with invalid signature type.
InvalidCertificateSignatureType,
/// We received a certificate with invalid signature.
InvalidCertificateSignature,
/// We received a certificate which includes invalid data.
InvalidCertificateData(String),
/// The presented SCT(s) were invalid.
InvalidSct(sct::Error),
/// A catch-all error for unlikely errors.
General(String),
/// We failed to figure out what time it currently is.
FailedToGetCurrentTime,
/// We failed to acquire random bytes from the system.
FailedToGetRandomBytes,
/// This function doesn't work until the TLS handshake
/// is complete.
HandshakeNotComplete,
/// The peer sent an oversized record/fragment.
PeerSentOversizedRecord,
/// An incoming connection did not support any known application protocol.
NoApplicationProtocol,
/// The `max_fragment_size` value supplied in configuration was too small,
/// or too large.
BadMaxFragmentSize,
}
fn join<T: fmt::Debug>(items: &[T]) -> String {
items
.iter()
.map(|x| format!("{:?}", x))
.collect::<Vec<String>>()
.join(" or ")
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::InappropriateMessage {
ref expect_types,
ref got_type,
} => write!(
f,
"received unexpected message: got {:?} when expecting {}",
got_type,
join::<ContentType>(expect_types)
),
Error::InappropriateHandshakeMessage {
ref expect_types,
ref got_type,
} => write!(
f,
"received unexpected handshake message: got {:?} when expecting {}",
got_type,
join::<HandshakeType>(expect_types)
),
Error::CorruptMessagePayload(ref typ) => {
write!(f, "received corrupt message of type {:?}", typ)
}
Error::PeerIncompatibleError(ref why) => write!(f, "peer is incompatible: {}", why),
Error::PeerMisbehavedError(ref why) => write!(f, "peer misbehaved: {}", why),
Error::AlertReceived(ref alert) => write!(f, "received fatal alert: {:?}", alert),
Error::InvalidCertificateEncoding => {
write!(f, "invalid peer certificate encoding")
}
Error::InvalidCertificateSignatureType => {
write!(f, "invalid peer certificate signature type")
}
Error::InvalidCertificateSignature => {
write!(f, "invalid peer certificate signature")
}
Error::InvalidCertificateData(ref reason) => {
write!(f, "invalid peer certificate contents: {}", reason)
}
Error::CorruptMessage => write!(f, "received corrupt message"),
Error::NoCertificatesPresented => write!(f, "peer sent no certificates"),
Error::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
Error::DecryptError => write!(f, "cannot decrypt peer's message"),
Error::EncryptError => write!(f, "cannot encrypt message"),
Error::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
Error::HandshakeNotComplete => write!(f, "handshake not complete"),
Error::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
Error::InvalidSct(ref err) => write!(f, "invalid certificate timestamp: {:?}", err),
Error::FailedToGetCurrentTime => write!(f, "failed to get current time"),
Error::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
Error::BadMaxFragmentSize => {
write!(f, "the supplied max_fragment_size was too small or large")
}
Error::General(ref err) => write!(f, "unexpected error: {}", err),
}
}
}
impl From<SystemTimeError> for Error {
#[inline]
fn from(_: SystemTimeError) -> Self {
Self::FailedToGetCurrentTime
}
}
impl StdError for Error {}
#[cfg(test)]
mod tests {
use super::Error;
#[test]
fn smoke() {
use crate::msgs::enums::{AlertDescription, ContentType, HandshakeType};
use sct;
let all = vec![
Error::InappropriateMessage {
expect_types: vec![ContentType::Alert],
got_type: ContentType::Handshake,
},
Error::InappropriateHandshakeMessage {
expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
got_type: HandshakeType::ServerHello,
},
Error::CorruptMessage,
Error::CorruptMessagePayload(ContentType::Alert),
Error::NoCertificatesPresented,
Error::DecryptError,
Error::PeerIncompatibleError("no tls1.2".to_string()),
Error::PeerMisbehavedError("inconsistent something".to_string()),
Error::AlertReceived(AlertDescription::ExportRestriction),
Error::InvalidCertificateEncoding,
Error::InvalidCertificateSignatureType,
Error::InvalidCertificateSignature,
Error::InvalidCertificateData("Data".into()),
Error::InvalidSct(sct::Error::MalformedSct),
Error::General("undocumented error".to_string()),
Error::FailedToGetCurrentTime,
Error::FailedToGetRandomBytes,
Error::HandshakeNotComplete,
Error::PeerSentOversizedRecord,
Error::NoApplicationProtocol,
Error::BadMaxFragmentSize,
];
for err in all {
println!("{:?}:", err);
println!(" fmt '{}'", err);
}
}
#[test]
fn time_error_mapping() {
use std::time::SystemTime;
let time_error = SystemTime::UNIX_EPOCH
.duration_since(SystemTime::now())
.unwrap_err();
let err: Error = time_error.into();
assert_eq!(err, Error::FailedToGetCurrentTime);
}
}

47
tls-core/src/key.rs Normal file
View File

@@ -0,0 +1,47 @@
use std::fmt;
/// This type contains a private key by value.
///
/// The private key must be DER-encoded ASN.1 in either
/// PKCS#8 or PKCS#1 format.
///
/// The `rustls-pemfile` crate can be used to extract
/// private keys from a PEM file in these formats.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct PrivateKey(pub Vec<u8>);
/// This type contains a single certificate by value.
///
/// The certificate must be DER-encoded X.509.
///
/// The `rustls-pemfile` crate can be used to parse a PEM file.
#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Certificate(pub Vec<u8>);
impl AsRef<[u8]> for Certificate {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl fmt::Debug for Certificate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use crate::utils::BsDebug;
f.debug_tuple("Certificate")
.field(&BsDebug(&self.0))
.finish()
}
}
#[cfg(test)]
mod test {
use super::Certificate;
#[test]
fn certificate_debug() {
assert_eq!(
"Certificate(b\"ab\")",
format!("{:?}", Certificate(b"ab".to_vec()))
);
}
}

View File

@@ -1,4 +1,13 @@
mod error;
#[cfg(feature = "ghash")]
pub mod ghash;
#[cfg(feature = "handshake")]
pub mod handshake;
pub mod key;
#[allow(missing_docs)]
#[macro_use]
pub mod msgs;
pub mod rand;
pub mod utils;
pub use error::Error;

View File

@@ -117,6 +117,21 @@ impl PayloadU8 {
}
}
pub struct PayloadU8Len(pub usize);
impl ring::hkdf::KeyType for PayloadU8Len {
fn len(&self) -> usize {
self.0
}
}
impl From<ring::hkdf::Okm<'_, PayloadU8Len>> for PayloadU8 {
fn from(okm: ring::hkdf::Okm<PayloadU8Len>) -> Self {
let mut r = vec![0u8; okm.len().0];
okm.fill(&mut r[..]).unwrap();
Self::new(r)
}
}
impl Codec for PayloadU8 {
fn encode(&self, bytes: &mut Vec<u8>) {
(self.0.len() as u8).encode(bytes);

View File

@@ -123,8 +123,7 @@ impl MessageDeframer {
* 0 ^ self.used
*/
self.buf
.copy_within(taken..self.used, 0);
self.buf.copy_within(taken..self.used, 0);
self.used -= taken;
} else if taken == self.used {
self.used = 0;
@@ -140,18 +139,20 @@ mod tests {
use std::convert::TryFrom;
use std::io;
const FIRST_MESSAGE: &[u8] = include_bytes!("../testdata/deframer-test.1.bin");
const SECOND_MESSAGE: &[u8] = include_bytes!("../testdata/deframer-test.2.bin");
const FIRST_MESSAGE: &[u8] = include_bytes!("../../testdata/deframer-test.1.bin");
const SECOND_MESSAGE: &[u8] = include_bytes!("../../testdata/deframer-test.2.bin");
const EMPTY_APPLICATIONDATA_MESSAGE: &[u8] =
include_bytes!("../testdata/deframer-empty-applicationdata.bin");
include_bytes!("../../testdata/deframer-empty-applicationdata.bin");
const INVALID_EMPTY_MESSAGE: &[u8] = include_bytes!("../testdata/deframer-invalid-empty.bin");
const INVALID_EMPTY_MESSAGE: &[u8] =
include_bytes!("../../testdata/deframer-invalid-empty.bin");
const INVALID_CONTENTTYPE_MESSAGE: &[u8] =
include_bytes!("../testdata/deframer-invalid-contenttype.bin");
include_bytes!("../../testdata/deframer-invalid-contenttype.bin");
const INVALID_VERSION_MESSAGE: &[u8] =
include_bytes!("../testdata/deframer-invalid-version.bin");
const INVALID_LENGTH_MESSAGE: &[u8] = include_bytes!("../testdata/deframer-invalid-length.bin");
include_bytes!("../../testdata/deframer-invalid-version.bin");
const INVALID_LENGTH_MESSAGE: &[u8] =
include_bytes!("../../testdata/deframer-invalid-length.bin");
struct ByteRead<'a> {
buf: &'a [u8],
@@ -223,8 +224,7 @@ mod tests {
fn input_error(d: &mut MessageDeframer) {
let error = io::Error::from(io::ErrorKind::TimedOut);
let mut rd = ErrorRead::new(error);
d.read(&mut rd)
.expect_err("error not propagated");
d.read(&mut rd).expect_err("error not propagated");
}
fn input_whole_incremental(d: &mut MessageDeframer, bytes: &[u8]) {

View File

@@ -10,9 +10,10 @@ use crate::msgs::enums::{HandshakeType, ProtocolVersion};
use crate::msgs::enums::{HashAlgorithm, ServerNameType, SignatureAlgorithm};
use crate::msgs::enums::{KeyUpdateRequest, NamedGroup, SignatureScheme};
use crate::rand;
use crate::Error;
#[cfg(feature = "logging")]
use crate::log::warn;
use tracing::warn;
use std::collections;
use std::fmt;
@@ -77,7 +78,7 @@ impl Codec for Random {
}
impl Random {
pub fn new() -> Result<Self, rand::GetRandomFailed> {
pub fn new() -> Result<Self, Error> {
let mut data = [0u8; 32];
rand::fill_random(&mut data)?;
Ok(Self(data))
@@ -147,7 +148,7 @@ impl Codec for SessionID {
}
impl SessionID {
pub fn random() -> Result<Self, rand::GetRandomFailed> {
pub fn random() -> Result<Self, Error> {
let mut data = [0u8; 32];
rand::fill_random(&mut data)?;
Ok(Self { data, len: 32 })

View File

@@ -26,9 +26,7 @@ fn test_read_fuzz_corpus() {
f.read_to_end(&mut bytes).unwrap();
let mut rd = Reader::init(&bytes);
let msg = OpaqueMessage::read(&mut rd)
.unwrap()
.into_plain_message();
let msg = OpaqueMessage::read(&mut rd).unwrap().into_plain_message();
println!("{:?}", msg);
let msg = match Message::try_from(msg) {
@@ -36,9 +34,7 @@ fn test_read_fuzz_corpus() {
Err(_) => continue,
};
let enc = PlainMessage::from(msg)
.into_unencrypted_opaque()
.encode();
let enc = PlainMessage::from(msg).into_unencrypted_opaque().encode();
assert_eq!(bytes.to_vec(), enc);
assert_eq!(bytes[..rd.used()].to_vec(), enc);
}
@@ -46,10 +42,6 @@ fn test_read_fuzz_corpus() {
#[test]
fn can_read_safari_client_hello() {
let _ = env_logger::Builder::new()
.filter(None, log::LevelFilter::Trace)
.try_init();
let bytes = b"\
\x16\x03\x01\x00\xeb\x01\x00\x00\xe7\x03\x03\xb6\x1f\xe4\x3a\x55\
\x90\x3e\xc0\x28\x9c\x12\xe0\x5c\x84\xea\x90\x1b\xfb\x11\xfc\xbd\

48
tls-core/src/msgs/mod.rs Normal file
View File

@@ -0,0 +1,48 @@
#![allow(clippy::upper_case_acronyms)]
#[macro_use]
mod macros;
pub mod alert;
pub mod base;
pub mod ccs;
pub mod codec;
pub mod deframer;
#[allow(non_camel_case_types)]
pub mod enums;
pub mod fragmenter;
#[allow(non_camel_case_types)]
pub mod handshake;
pub mod hsjoiner;
pub mod message;
#[cfg(test)]
mod handshake_test;
#[cfg(test)]
mod enums_test;
#[cfg(test)]
mod message_test;
#[cfg(test)]
mod test {
use std::convert::TryFrom;
#[test]
fn smoketest() {
use super::codec::Reader;
use super::message::{Message, OpaqueMessage};
let bytes = include_bytes!("handshake-test.1.bin");
let mut r = Reader::init(bytes);
while r.any_left() {
let m = OpaqueMessage::read(&mut r).unwrap();
let out = m.clone().encode();
assert!(!out.is_empty());
Message::try_from(m.into_plain_message()).unwrap();
}
}
}

27
tls-core/src/rand.rs Normal file
View File

@@ -0,0 +1,27 @@
use crate::msgs::codec;
use crate::Error;
use rand::{thread_rng, Rng};
/// Fill the whole slice with random material.
pub fn fill_random(bytes: &mut [u8]) -> Result<(), Error> {
thread_rng()
.try_fill(bytes)
.map_err(|_| Error::General("failed to get random from system".to_string()))
}
/// Make a Vec<u8> of the given size
/// containing random material.
pub fn random_vec(len: usize) -> Result<Vec<u8>, Error> {
let mut v = vec![0; len];
fill_random(&mut v)?;
Ok(v)
}
/// Return a uniformly random u32.
pub fn random_u32() -> Result<u32, Error> {
let mut buf = [0u8; 4];
fill_random(&mut buf)?;
codec::decode_u32(&buf).ok_or(Error::General(
"failed to get random from system".to_string(),
))
}

View File

@@ -0,0 +1,77 @@
use std::fmt;
/// Alternative implementation of `fmt::Debug` for byte slice.
///
/// Standard `Debug` implementation for `[u8]` is comma separated
/// list of numbers. Since large amount of byte strings are in fact
/// ASCII strings or contain a lot of ASCII strings (e. g. HTTP),
/// it is convenient to print strings as ASCII when possible.
///
/// This struct wraps `&[u8]` just to override `fmt::Debug`.
///
/// `BsDebug` is not a part of public API of bytes crate.
pub(crate) struct BsDebug<'a>(pub(crate) &'a [u8]);
impl<'a> fmt::Debug for BsDebug<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "b\"")?;
for &c in self.0 {
// https://doc.rust-lang.org/reference.html#byte-escapes
if c == b'\n' {
write!(fmt, "\\n")?;
} else if c == b'\r' {
write!(fmt, "\\r")?;
} else if c == b'\t' {
write!(fmt, "\\t")?;
} else if c == b'\\' || c == b'"' {
write!(fmt, "\\{}", c as char)?;
} else if c == b'\0' {
write!(fmt, "\\0")?;
// ASCII printable
} else if (0x20..0x7f).contains(&c) {
write!(fmt, "{}", c as char)?;
} else {
write!(fmt, "\\x{:02x}", c)?;
}
}
write!(fmt, "\"")?;
Ok(())
}
}
#[cfg(test)]
mod test {
use super::BsDebug;
#[test]
fn debug() {
let vec: Vec<_> = (0..0x100).map(|b| b as u8).collect();
let expected = "b\"\
\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\
\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\
\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\
\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\
\x20!\\\"#$%&'()*+,-./0123456789:;<=>?\
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_\
`abcdefghijklmnopqrstuvwxyz{|}~\\x7f\
\\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87\
\\x88\\x89\\x8a\\x8b\\x8c\\x8d\\x8e\\x8f\
\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\
\\x98\\x99\\x9a\\x9b\\x9c\\x9d\\x9e\\x9f\
\\xa0\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6\\xa7\
\\xa8\\xa9\\xaa\\xab\\xac\\xad\\xae\\xaf\
\\xb0\\xb1\\xb2\\xb3\\xb4\\xb5\\xb6\\xb7\
\\xb8\\xb9\\xba\\xbb\\xbc\\xbd\\xbe\\xbf\
\\xc0\\xc1\\xc2\\xc3\\xc4\\xc5\\xc6\\xc7\
\\xc8\\xc9\\xca\\xcb\\xcc\\xcd\\xce\\xcf\
\\xd0\\xd1\\xd2\\xd3\\xd4\\xd5\\xd6\\xd7\
\\xd8\\xd9\\xda\\xdb\\xdc\\xdd\\xde\\xdf\
\\xe0\\xe1\\xe2\\xe3\\xe4\\xe5\\xe6\\xe7\
\\xe8\\xe9\\xea\\xeb\\xec\\xed\\xee\\xef\
\\xf0\\xf1\\xf2\\xf3\\xf4\\xf5\\xf6\\xf7\
\\xf8\\xf9\\xfa\\xfb\\xfc\\xfd\\xfe\\xff\"";
assert_eq!(expected, format!("{:?}", BsDebug(&vec)));
}
}

View File

@@ -0,0 +1,3 @@
mod bs_debug;
pub(crate) use bs_debug::*;

BIN
tls-core/testdata/cert-arstechnica.0.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-arstechnica.1.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-arstechnica.2.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-arstechnica.3.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-duckduckgo.0.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-duckduckgo.1.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-github.0.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-github.1.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-google.0.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-google.1.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-google.2.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-hn.0.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-hn.1.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-reddit.0.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-reddit.1.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-rustlang.0.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-rustlang.1.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-rustlang.2.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-rustlang.3.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-servo.0.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-servo.1.der vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
tls-core/testdata/cert-twitter.0.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-twitter.1.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-wapo.0.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-wapo.1.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-wikipedia.0.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/cert-wikipedia.1.der vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
tls-core/testdata/deframer-test.1.bin vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/deframer-test.2.bin vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/eddsakey.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/nistp256key.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/nistp256key.pkcs8.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/nistp384key.der vendored Normal file

Binary file not shown.

BIN
tls-core/testdata/nistp384key.pkcs8.der vendored Normal file

Binary file not shown.

1
tls-core/testdata/prf-result.1.bin vendored Normal file
View File

@@ -0,0 +1 @@
ЦР)╨r{А{█& U|тSб╙╡цт∙2⌡RтФшZk0▒И

1
tls-core/testdata/prf-result.2.bin vendored Normal file
View File

@@ -0,0 +1 @@
aυ<61>Η<EFBFBD>ΕΒ<01>nz<6E>µνΝγωLf<4C>*F8ΧΥ²ƒ-φx<CF86>uΗ~<7E>m†Η\Eβ΄ τ΅q;'7hC%χά<CF87>¨ο">κ…Ώhe= ό@VΨπ%Δ]ί¦ζώΗπT΄ Φς<CEA6>Π£#>I<>¤>uΕcνΎ"ώ%N3΅°ιφΉfuΎΗΠ„VXά<58>9uE@@Ήτlz@αΈψ ¦

BIN
tls-core/testdata/rsa2048key.pkcs1.der vendored Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More