readme: add cert guide

master
occheung 2021-01-29 12:31:04 +08:00
parent 99f92f84ba
commit 5e11fd664e
1 changed files with 57 additions and 2 deletions

View File

@ -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!( `<path-to-certificate>` );
// 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);
```