From 5e11fd664e1c5fb7195b1af3af26549fcff66901 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 29 Jan 2021 12:31:04 +0800 Subject: [PATCH] readme: add cert guide --- README.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 81d1dd9..2bff10b 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Use `TlsSocketHandle` to gain access to a TLS Socket indirectly. ```rust // Prepare a socket set for TLS sockets let mut tls_socket_entries: [_; 1] = Default::default(); - let mut tls_socket_set = smoltcp_tls::set::TlsSocketSet::new( + let mut tls_socket_set = SaiTLS::set::TlsSocketSet::new( &mut tls_socket_entries[..] ); // Use TLS socket set & handle to access TLS socket @@ -83,7 +83,7 @@ Use `TlsSocketHandle` to gain access to a TLS Socket indirectly. ## Polling The `poll(..)` function substitutes the `EthernetInterface.poll(..)` function in smoltcp. ```rust - smoltcp_tls::poll( + SaiTLS::poll( Some(&mut smoltcp_sockets), // Optional socket set from smoltcp &mut tls_socket_set, &mut ethernet_interface, @@ -92,5 +92,60 @@ The `poll(..)` function substitutes the `EthernetInterface.poll(..)` function in ``` Sockets in either `smoltcp_sockets` or `tls_socket_set` will be updated. +## Authentication on SaiTLS side +If necessary, SaiTLS will send X.509 certificate to the remote side, designated in the constructor. This requires X.509 certificate and its associated private key to be loaded onto the socket. A X.509 self-signed certificate and the signature private key can be generated by OpenSSL using the following command: +``` +openssl req -x509 -newkey rsa:1024 -sha256 -nodes -keyout key.der -out cert.der -days 30 -outform DER +``` +This will generate a self-signed certificate in DER format as `cert.der`, signed by an RSA key with 1024 bits as `key.der`. The certificate supplied to SaiTLS must be in DER format. + +The `include_bytes!()` Rust macro can load the DER certificate as a binary slice. +Private/Secrete key needs to be instantiated by the corresponding RustCrypto/Dalek library. The following is an example of loading `cert.der` and `key.der` into the constructor of `TLSSocket`. + +```Rust +// This line includes the certificate in DER format +const CERT: &'static [u8] = include_bytes!( `` ); +// These lines contains components of the RSA private key +const PRIVATE_KEY_MOD: &'static [u8] = ... ; +const PUBLIC_KEY_EXP: &'static [u8] = &[ 0x01, 0x00, 0x01 ]; +const PRIVATE_KEY_EXP: &'static [u8] = ... ; +const CLIENT_PRIME_1: &'static [u8] = ... ; +const CLIENT_PRIME_2: &'static [u8] = ... ; +``` +The exact values of these constants can be found by printing out the content using OpenSSL, such as the following command. +``` +openssl rsa -in key.der -text +``` +The private key can then be assembled as such: +```Rust +let mut prime_vec = alloc::vec::Vec::new(); +prime_vec.push(rsa::BigUint::from_bytes_be(&CLIENT_PRIME_1)); +prime_vec.push(rsa::BigUint::from_bytes_be(&CLIENT_PRIME_2)); + +let rsa_key = rsa::RSAPrivateKey::from_components( + rsa::BigUint::from_bytes_be(CLIENT_PRIVATE_KEY_MOD), + rsa::BigUint::from_bytes_be(CLIENT_PUBLIC_KEY_EXP), + rsa::BigUint::from_bytes_be(CLIENT_PRIVATE_KEY_EXP), + prime_vec +); +``` +Finally, the private key and the certificate are loaded onto the socket. +```Rust +let mut tls_socket = TlsSocket::new( + tcp_socket, + &mut rng_struct, + Some((cert_private_key, alloc::vec![CLIENT_CERT])) +); +``` +Loading more than 1 certificate (i.e. a certificate chain) is experimental. Use at your own risk! + +Note that the remote side may not necessarily accept the self-signed certificate. It is entirely up to the remote side to accept or reject your provided certificate. Designation of trusted files might be helpful (e.g. the `--trustfile` option in Ncat). + ## Feature `nal_tcp_stack` Implements `TcpStack` in embedded-nal (v0.1.0) for `TlsSocket`. This disguises `TlsSocket` as just another TCP socket, potentially useful for implementating application layer protocols (e.g. MQTT in minimq). + +Usage: +```Rust +let tls_socket_set = SaiTLS::set::TlsSocketSet::new( .. ); +let tls_stack = NetworkStack::new(tls_socket_set); +```