mirror of https://github.com/vacp2p/nim-webrtc.git
143 lines
4.6 KiB
Nim
143 lines
4.6 KiB
Nim
# Nim-WebRTC
|
|
# Copyright (c) 2023 Status Research & Development GmbH
|
|
# Licensed under either of
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
|
# at your option.
|
|
# This file may not be copied, modified, or distributed except according to
|
|
# those terms.
|
|
|
|
import std/times
|
|
import chronos
|
|
import webrtc_connection
|
|
|
|
import mbedtls/ssl
|
|
import mbedtls/pk
|
|
import mbedtls/md
|
|
import mbedtls/entropy
|
|
import mbedtls/ctr_drbg
|
|
import mbedtls/rsa
|
|
import mbedtls/x509
|
|
import mbedtls/x509_crt
|
|
import mbedtls/bignum
|
|
import mbedtls/error
|
|
import mbedtls/net_sockets
|
|
|
|
type
|
|
DtlsConn* = ref object of WebRTCConn
|
|
recvData: seq[seq[byte]]
|
|
recvEvent: AsyncEvent
|
|
sendEvent: AsyncEvent
|
|
|
|
entropy: mbedtls_entropy_context
|
|
ctr_drbg: mbedtls_ctr_drbg_context
|
|
|
|
config: mbedtls_ssl_config
|
|
ssl: mbedtls_ssl_context
|
|
|
|
proc mbedtls_pk_rsa(pk: mbedtls_pk_context): ptr mbedtls_rsa_context =
|
|
var key = pk
|
|
case mbedtls_pk_get_type(addr key):
|
|
of MBEDTLS_PK_RSA:
|
|
return cast[ptr mbedtls_rsa_context](pk.private_pk_ctx)
|
|
else:
|
|
return nil
|
|
|
|
proc generateKey(self: DtlsConn): mbedtls_pk_context =
|
|
var res: mbedtls_pk_context
|
|
mb_pk_init(res)
|
|
discard mbedtls_pk_setup(addr res, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA))
|
|
mb_rsa_gen_key(mb_pk_rsa(res), mbedtls_ctr_drbg_random, self.ctr_drbg, 4096, 65537)
|
|
return res
|
|
|
|
proc generateCertificate(self: DtlsConn): mbedtls_x509_crt =
|
|
let
|
|
name = "C=FR,O=webrtc,CN=wbrtc"
|
|
time_format = initTimeFormat("YYYYMMddHHmmss")
|
|
time_from = times.now().format(time_format)
|
|
time_to = (times.now() + times.years(1)).format(time_format)
|
|
|
|
|
|
var issuer_key = self.generateKey()
|
|
var write_cert: mbedtls_x509write_cert
|
|
var serial_mpi: mbedtls_mpi
|
|
mb_x509write_crt_init(write_cert)
|
|
mb_x509write_crt_set_md_alg(write_cert, MBEDTLS_MD_SHA256);
|
|
mb_x509write_crt_set_subject_key(write_cert, issuer_key)
|
|
mb_x509write_crt_set_issuer_key(write_cert, issuer_key)
|
|
mb_x509write_crt_set_subject_name(write_cert, name)
|
|
mb_x509write_crt_set_issuer_name(write_cert, name)
|
|
mb_x509write_crt_set_validity(write_cert, time_from, time_to)
|
|
mb_x509write_crt_set_basic_constraints(write_cert, 0, -1)
|
|
mb_x509write_crt_set_subject_key_identifier(write_cert)
|
|
mb_x509write_crt_set_authority_key_identifier(write_cert)
|
|
mb_mpi_init(serial_mpi)
|
|
let serial_hex = mb_mpi_read_string(serial_mpi, 16)
|
|
mb_x509write_crt_set_serial(write_cert, serial_mpi)
|
|
let buf = mb_x509write_crt_pem(write_cert, 4096, mbedtls_ctr_drbg_random, self.ctr_drbg)
|
|
mb_x509_crt_parse(result, buf)
|
|
|
|
proc dtlsSend*(ctx: pointer, buf: ptr byte, len: uint): cint {.cdecl.} =
|
|
echo "dtlsSend: "
|
|
let self = cast[ptr DtlsConn](ctx)
|
|
self.sendEvent.fire()
|
|
|
|
proc dtlsRecv*(ctx: pointer, buf: ptr byte, len: uint): cint {.cdecl.} =
|
|
echo "dtlsRecv: "
|
|
let self = cast[ptr DtlsConn](ctx)[]
|
|
self.recvEvent.fire()
|
|
|
|
method init*(self: DtlsConn, conn: WebRTCConn, address: TransportAddress) {.async.} =
|
|
await procCall(WebRTCConn(self).init(conn, address))
|
|
self.recvEvent = AsyncEvent()
|
|
self.sendEvent = AsyncEvent()
|
|
|
|
mb_ctr_drbg_init(self.ctr_drbg)
|
|
mb_entropy_init(self.entropy)
|
|
mb_ctr_drbg_seed(self.ctr_drbg, mbedtls_entropy_func,
|
|
self.entropy, nil, 0)
|
|
var
|
|
srvcert = self.generateCertificate()
|
|
pkey = self.generateKey()
|
|
selfvar = self
|
|
|
|
mb_ssl_init(self.ssl)
|
|
mb_ssl_config_init(self.config)
|
|
mb_ssl_config_defaults(self.config, MBEDTLS_SSL_IS_SERVER,
|
|
MBEDTLS_SSL_TRANSPORT_DATAGRAM,
|
|
MBEDTLS_SSL_PRESET_DEFAULT)
|
|
mb_ssl_conf_rng(self.config, mbedtls_ctr_drbg_random, self.ctr_drbg)
|
|
mb_ssl_conf_read_timeout(self.config, 10000) # in milliseconds
|
|
mb_ssl_conf_ca_chain(self.config, srvcert.next, nil)
|
|
mb_ssl_conf_own_cert(self.config, srvcert, pkey)
|
|
# cookies ?
|
|
mb_ssl_setup(self.ssl, self.config)
|
|
mb_ssl_session_reset(self.ssl)
|
|
mb_ssl_set_bio(self.ssl, cast[pointer](addr selfvar),
|
|
dtlsSend, dtlsRecv, nil)
|
|
while true:
|
|
mb_ssl_handshake(self.ssl)
|
|
|
|
method close*(self: DtlsConn) {.async.} =
|
|
discard
|
|
|
|
method write*(self: DtlsConn, msg: seq[byte]) {.async.} =
|
|
var buf = msg
|
|
self.sendEvent.clear()
|
|
discard mbedtls_ssl_write(addr self.ssl, cast[ptr byte](buf.cstring), buf.len())
|
|
await self.sendEvent.wait()
|
|
|
|
method read*(self: DtlsConn): Future[seq[byte]] {.async.} =
|
|
var res = newString(4096)
|
|
self.recvEvent.clear()
|
|
discard mbedtls_ssl_read(addr self.ssl, cast[ptr byte](res.cstring), 4096)
|
|
await self.recvEvent.wait()
|
|
|
|
proc main {.async.} =
|
|
let laddr = initTAddress("127.0.0.1:" & "4242")
|
|
var dtls = DtlsConn()
|
|
await dtls.init(nil, laddr)
|
|
let cert = dtls.generateCertificate()
|
|
|
|
waitFor(main())
|