WebRTC certificate improvement
This commit is contained in:
parent
37cbafe284
commit
e6489f2d6a
4 changed files with 83 additions and 24 deletions
|
@ -3,9 +3,9 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
Certificate::Certificate() : rsa_ctx(NULL){
|
Certificate::Certificate(){
|
||||||
memset((void *)&cert, 0x00, sizeof(cert));
|
mbedtls_pk_init(&key);
|
||||||
memset((void *)&key, 0x00, sizeof(key));
|
mbedtls_x509_crt_init(&cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Certificate::init(const std::string &countryName, const std::string &organization,
|
int Certificate::init(const std::string &countryName, const std::string &organization,
|
||||||
|
@ -14,6 +14,7 @@ int Certificate::init(const std::string &countryName, const std::string &organiz
|
||||||
mbedtls_ctr_drbg_context rand_ctx ={};
|
mbedtls_ctr_drbg_context rand_ctx ={};
|
||||||
mbedtls_entropy_context entropy_ctx ={};
|
mbedtls_entropy_context entropy_ctx ={};
|
||||||
mbedtls_x509write_cert write_cert ={};
|
mbedtls_x509write_cert write_cert ={};
|
||||||
|
mbedtls_rsa_context *rsa_ctx;
|
||||||
|
|
||||||
const char *personalisation = "mbedtls-self-signed-key";
|
const char *personalisation = "mbedtls-self-signed-key";
|
||||||
std::string subject_name = "C=" + countryName + ",O=" + organization + ",CN=" + commonName;
|
std::string subject_name = "C=" + countryName + ",O=" + organization + ",CN=" + commonName;
|
||||||
|
@ -58,7 +59,6 @@ int Certificate::init(const std::string &countryName, const std::string &organiz
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize the public key context
|
// initialize the public key context
|
||||||
mbedtls_pk_init(&key);
|
|
||||||
r = mbedtls_pk_setup(&key, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
|
r = mbedtls_pk_setup(&key, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
|
||||||
if (0 != r){
|
if (0 != r){
|
||||||
FAIL_MSG("Faild to initialize the PK context.");
|
FAIL_MSG("Faild to initialize the PK context.");
|
||||||
|
@ -66,6 +66,8 @@ int Certificate::init(const std::string &countryName, const std::string &organiz
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//This call returns a reference to the existing RSA context inside the key.
|
||||||
|
//Hence, it does not need to be cleaned up later.
|
||||||
rsa_ctx = mbedtls_pk_rsa(key);
|
rsa_ctx = mbedtls_pk_rsa(key);
|
||||||
if (NULL == rsa_ctx){
|
if (NULL == rsa_ctx){
|
||||||
FAIL_MSG("Failed to get the RSA context from from the public key context (key).");
|
FAIL_MSG("Failed to get the RSA context from from the public key context (key).");
|
||||||
|
@ -181,8 +183,6 @@ int Certificate::init(const std::string &countryName, const std::string &organiz
|
||||||
// char. @todo there must be a way to convert the write
|
// char. @todo there must be a way to convert the write
|
||||||
// struct into a `mbedtls_x509_cert` w/o calling this parse
|
// struct into a `mbedtls_x509_cert` w/o calling this parse
|
||||||
// function.
|
// function.
|
||||||
mbedtls_x509_crt_init(&cert);
|
|
||||||
|
|
||||||
r = mbedtls_x509_crt_parse(&cert, (const unsigned char *)buf, strlen((char *)buf) + 1);
|
r = mbedtls_x509_crt_parse(&cert, (const unsigned char *)buf, strlen((char *)buf) + 1);
|
||||||
if (0 != r){
|
if (0 != r){
|
||||||
mbedtls_strerror(r, (char *)buf, sizeof(buf));
|
mbedtls_strerror(r, (char *)buf, sizeof(buf));
|
||||||
|
@ -198,24 +198,31 @@ error:
|
||||||
mbedtls_entropy_free(&entropy_ctx);
|
mbedtls_entropy_free(&entropy_ctx);
|
||||||
mbedtls_x509write_crt_free(&write_cert);
|
mbedtls_x509write_crt_free(&write_cert);
|
||||||
mbedtls_mpi_free(&serial_mpi);
|
mbedtls_mpi_free(&serial_mpi);
|
||||||
|
|
||||||
if (r < 0){shutdown();}
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Certificate::shutdown(){
|
Certificate::~Certificate(){
|
||||||
rsa_ctx = NULL;
|
|
||||||
mbedtls_pk_free(&key);
|
mbedtls_pk_free(&key);
|
||||||
mbedtls_x509_crt_free(&cert);
|
mbedtls_x509_crt_free(&cert);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Certificate::getFingerprintSha256(){
|
/// Loads a single file into the certificate. Returns true on success.
|
||||||
|
bool Certificate::loadCert(const std::string & certFile){
|
||||||
|
if (!certFile.size()){return true;}
|
||||||
|
return mbedtls_x509_crt_parse_file(&cert, certFile.c_str()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Loads a single key. Returns true on success.
|
||||||
|
bool Certificate::loadKey(const std::string & keyFile){
|
||||||
|
if (!keyFile.size()){return true;}
|
||||||
|
return mbedtls_pk_parse_keyfile(&key, keyFile.c_str(), 0) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculates SHA256 fingerprint over the loaded certificate(s)
|
||||||
|
/// Returns the fingerprint as hex-string.
|
||||||
|
std::string Certificate::getFingerprintSha256() const{
|
||||||
uint8_t fingerprint_raw[32] ={};
|
uint8_t fingerprint_raw[32] ={};
|
||||||
uint8_t fingerprint_hex[128] ={};
|
uint8_t fingerprint_hex[128] ={};
|
||||||
|
|
||||||
mbedtls_sha256(cert.raw.p, cert.raw.len, fingerprint_raw, 0);
|
mbedtls_sha256(cert.raw.p, cert.raw.len, fingerprint_raw, 0);
|
||||||
|
|
||||||
for (int i = 0; i < 32; ++i){
|
for (int i = 0; i < 32; ++i){
|
||||||
|
@ -223,7 +230,6 @@ std::string Certificate::getFingerprintSha256(){
|
||||||
}
|
}
|
||||||
|
|
||||||
fingerprint_hex[32 * 3] = '\0';
|
fingerprint_hex[32 * 3] = '\0';
|
||||||
|
|
||||||
std::string result = std::string((char *)fingerprint_hex + 1, (32 * 3) - 1);
|
std::string result = std::string((char *)fingerprint_hex + 1, (32 * 3) - 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,12 +23,13 @@
|
||||||
class Certificate{
|
class Certificate{
|
||||||
public:
|
public:
|
||||||
Certificate();
|
Certificate();
|
||||||
|
bool loadCert(const std::string & certFile);
|
||||||
|
bool loadKey(const std::string & certFile);
|
||||||
int init(const std::string &countryName, const std::string &organization, const std::string &commonName);
|
int init(const std::string &countryName, const std::string &organization, const std::string &commonName);
|
||||||
int shutdown();
|
~Certificate();
|
||||||
std::string getFingerprintSha256();
|
std::string getFingerprintSha256() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
mbedtls_x509_crt cert;
|
mbedtls_x509_crt cert;
|
||||||
mbedtls_pk_context key; /* key context, stores private and public key. */
|
mbedtls_pk_context key; /* key context, stores private and public key. */
|
||||||
mbedtls_rsa_context *rsa_ctx; /* rsa context, stored in key_ctx */
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <mist/timing.h>
|
#include <mist/timing.h>
|
||||||
#include <mist/url.h>
|
#include <mist/url.h>
|
||||||
#include <netdb.h> // ifaddr, listing ip addresses.
|
#include <netdb.h> // ifaddr, listing ip addresses.
|
||||||
|
#include <mist/stream.h>
|
||||||
|
|
||||||
namespace Mist{
|
namespace Mist{
|
||||||
|
|
||||||
|
@ -79,16 +80,55 @@ namespace Mist{
|
||||||
volkswagenMode = false;
|
volkswagenMode = false;
|
||||||
syncedNTPClock = false;
|
syncedNTPClock = false;
|
||||||
|
|
||||||
|
|
||||||
|
JSON::Value & certOpt = config->getOption("cert", true);
|
||||||
|
JSON::Value & keyOpt = config->getOption("key", true);
|
||||||
|
|
||||||
|
//Attempt to read certificate config from other connectors
|
||||||
|
if (certOpt.size() < 2 || keyOpt.size() < 2){
|
||||||
|
Util::DTSCShmReader rProto(SHM_PROTO);
|
||||||
|
DTSC::Scan prtcls = rProto.getScan();
|
||||||
|
unsigned int pro_cnt = prtcls.getSize();
|
||||||
|
for (unsigned int i = 0; i < pro_cnt; ++i){
|
||||||
|
if (prtcls.getIndice(i).hasMember("key") && prtcls.getIndice(i).hasMember("cert")){
|
||||||
|
std::string conn = prtcls.getIndice(i).getMember("connector").asString();
|
||||||
|
INFO_MSG("No cert/key configured for WebRTC explicitly, reading from %s connector config", conn.c_str());
|
||||||
|
JSON::Value newCert = prtcls.getIndice(i).getMember("cert").asJSON();
|
||||||
|
certOpt.shrink(0);
|
||||||
|
jsonForEach(newCert, k){certOpt.append(*k);}
|
||||||
|
keyOpt.shrink(0);
|
||||||
|
keyOpt.append(prtcls.getIndice(i).getMember("key").asJSON());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (certOpt.size() < 2 || keyOpt.size() < 2){
|
||||||
if (cert.init("NL", "webrtc", "webrtc") != 0){
|
if (cert.init("NL", "webrtc", "webrtc") != 0){
|
||||||
onFail("Failed to create the certificate.", true);
|
onFail("Failed to create the certificate.", true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
// Read certificate chain(s)
|
||||||
|
jsonForEach(certOpt, it){
|
||||||
|
if (!cert.loadCert(it->asStringRef())){
|
||||||
|
WARN_MSG("Could not load any certificates from file: %s", it->asStringRef().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read key
|
||||||
|
if (!cert.loadKey(config->getString("key"))){
|
||||||
|
FAIL_MSG("Could not load any keys from file: %s", config->getString("key").c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (dtlsHandshake.init(&cert.cert, &cert.key, onDTLSHandshakeWantsToWriteCallback) != 0){
|
if (dtlsHandshake.init(&cert.cert, &cert.key, onDTLSHandshakeWantsToWriteCallback) != 0){
|
||||||
onFail("Failed to initialize the dtls-srtp handshake helper.", true);
|
onFail("Failed to initialize the dtls-srtp handshake helper.", true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sdpAnswer.setFingerprint(cert.getFingerprintSha256());
|
sdpAnswer.setFingerprint(cert.getFingerprintSha256());
|
||||||
|
|
||||||
classPointer = this;
|
classPointer = this;
|
||||||
|
|
||||||
setBlocking(false);
|
setBlocking(false);
|
||||||
|
@ -107,7 +147,6 @@ namespace Mist{
|
||||||
if (dtlsHandshake.shutdown() != 0){
|
if (dtlsHandshake.shutdown() != 0){
|
||||||
FAIL_MSG("Failed to cleanly shutdown the dtls handshake.");
|
FAIL_MSG("Failed to cleanly shutdown the dtls handshake.");
|
||||||
}
|
}
|
||||||
if (cert.shutdown() != 0){FAIL_MSG("Failed to cleanly shutdown the certificate.");}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the WebRTC output. This is where we define what
|
// Initialize the WebRTC output. This is where we define what
|
||||||
|
@ -218,6 +257,19 @@ namespace Mist{
|
||||||
capa["optional"]["losttimeoutmobile"]["type"] = "uint";
|
capa["optional"]["losttimeoutmobile"]["type"] = "uint";
|
||||||
capa["optional"]["losttimeoutmobile"]["default"] = 90;
|
capa["optional"]["losttimeoutmobile"]["default"] = 90;
|
||||||
|
|
||||||
|
capa["optional"]["cert"]["name"] = "Certificate";
|
||||||
|
capa["optional"]["cert"]["help"] = "(Root) certificate(s) file(s) to append to chain";
|
||||||
|
capa["optional"]["cert"]["option"] = "--cert";
|
||||||
|
capa["optional"]["cert"]["short"] = "C";
|
||||||
|
capa["optional"]["cert"]["default"] = "";
|
||||||
|
capa["optional"]["cert"]["type"] = "str";
|
||||||
|
capa["optional"]["key"]["name"] = "Key";
|
||||||
|
capa["optional"]["key"]["help"] = "Private key for SSL";
|
||||||
|
capa["optional"]["key"]["option"] = "--key";
|
||||||
|
capa["optional"]["key"]["short"] = "K";
|
||||||
|
capa["optional"]["key"]["default"] = "";
|
||||||
|
capa["optional"]["key"]["type"] = "str";
|
||||||
|
|
||||||
config->addOptionsFromCapabilities(capa);
|
config->addOptionsFromCapabilities(capa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@ namespace Mist{
|
||||||
int onDTLSHandshakeWantsToWrite(const uint8_t *data, int *nbytes);
|
int onDTLSHandshakeWantsToWrite(const uint8_t *data, int *nbytes);
|
||||||
void onRTPSorterHasPacket(size_t tid, const RTP::Packet &pkt);
|
void onRTPSorterHasPacket(size_t tid, const RTP::Packet &pkt);
|
||||||
void onDTSCConverterHasPacket(const DTSC::Packet &pkt);
|
void onDTSCConverterHasPacket(const DTSC::Packet &pkt);
|
||||||
void onDTSCConverterHasInitData(const uint64_t trackID, const std::string &initData);
|
void onDTSCConverterHasInitData(const size_t trackID, const std::string &initData);
|
||||||
void onRTPPacketizerHasRTPPacket(const char *data, size_t nbytes);
|
void onRTPPacketizerHasRTPPacket(const char *data, size_t nbytes);
|
||||||
void onRTPPacketizerHasRTCPPacket(const char *data, uint32_t nbytes);
|
void onRTPPacketizerHasRTCPPacket(const char *data, uint32_t nbytes);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue