Skip to content

Commit

Permalink
Add certificate DN parsing for BR implementation (SmingHub#44)
Browse files Browse the repository at this point in the history
* Don't generate certificate if SSL is disabled

* Invoke `sslInitSession` from within `sslCreateSession`.

* Enable information/debug messages only when SSL_DEBUG is defined

* Further simplify TcpConnection::write

* Add certificate DN parsing for BR implementation

Revise interface to use standard DN and RDN values
  • Loading branch information
mikee47 authored and slav-at-attachix committed Jan 1, 2020
1 parent e653b0c commit 2de9d6b
Show file tree
Hide file tree
Showing 25 changed files with 548 additions and 116 deletions.
56 changes: 56 additions & 0 deletions Sming/Components/ssl/Axtls/AxCertificate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/SmingHub/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
*
* AxCertificate.cpp
*
****/

#include "AxCertificate.h"

namespace Ssl
{
String AxCertificate::getName(DN dn, RDN rdn) const
{
if(ssl == nullptr || ssl->x509_ctx == nullptr) {
return nullptr;
}

int dnType;
switch(rdn) {
case RDN::COMMON_NAME:
dnType = X509_COMMON_NAME;
break;
case RDN::ORGANIZATION_NAME:
dnType = X509_ORGANIZATION;
break;
case RDN::ORGANIZATIONAL_UNIT_NAME:
dnType = X509_ORGANIZATIONAL_UNIT;
break;
case RDN::LOCALITY_NAME:
dnType = X509_LOCATION;
break;
case RDN::COUNTRY_NAME:
dnType = X509_COUNTRY;
break;
case RDN::STATE_OR_PROVINCE_NAME:
dnType = X509_STATE;
break;
default:
return nullptr;
}

switch(dn) {
case DN::ISSUER:
return ssl->x509_ctx->ca_cert_dn[dnType];

case DN::SUBJECT:
return ssl->x509_ctx->cert_dn[dnType];
default:
return nullptr;
}
}

} // namespace Ssl
5 changes: 1 addition & 4 deletions Sming/Components/ssl/Axtls/AxCertificate.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,7 @@ class AxCertificate : public Certificate
return (ssl_match_spki_sha256(ssl, hash) == 0);
}

const String getName(Name name) const override
{
return String(ssl_get_cert_dn(ssl, int(name)));
}
String getName(DN dn, RDN rdn) const override;

private:
SSL* ssl;
Expand Down
5 changes: 1 addition & 4 deletions Sming/Components/ssl/Axtls/AxConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*
****/

#include <SslDebug.h>
#include "AxConnection.h"
#include "AxContext.h"
#include <Network/Ssl/Session.h>
Expand All @@ -33,16 +34,12 @@ int AxConnection::write(const uint8_t* data, size_t length)

int available = tcp_sndbuf(tcp);
if(available < required) {
#ifdef SSL_DEBUG
debug_i("SSL: Required: %d, Available: %d", required, available);
#endif
return SSL_NOT_OK;
}

int written = ssl_write(ssl, data, length);
#ifdef SSL_DEBUG
debug_d("SSL: Write len: %d, Written: %d", length, written);
#endif
if(written < 0) {
debug_e("SSL: Write Error: %d", written);
}
Expand Down
144 changes: 144 additions & 0 deletions Sming/Components/ssl/BearSsl/Asn1Parser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/SmingHub/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
*
* Asn1Parser.h
*
* A very simple helper class consisting of code based on asn1_name() in axTLS.
*
****/

#pragma once

#include <stdint.h>

enum ASN1 {
ASN1_BOOLEAN = 0x01,
ASN1_INTEGER = 0x02,
ASN1_BIT_STRING = 0x03,
ASN1_OCTET_STRING = 0x04,
ASN1_NULL = 0x05,
ASN1_OID = 0x06,
ASN1_PRINTABLE_STR2 = 0x0c,
ASN1_PRINTABLE_STR = 0x13,
ASN1_TELETEX_STR = 0x14,
ASN1_IA5_STR = 0x16,
ASN1_UTC_TIME = 0x17,
ASN1_GENERALIZED_TIME = 0x18,
ASN1_UNICODE_STR = 0x1e,
ASN1_SEQUENCE = 0x30,
ASN1_SET = 0x31,
ASN1_IMPLICIT_TAG = 0x80,
ASN1_CONTEXT_DNSNAME = 0x82,
ASN1_EXPLICIT_TAG = 0xa0,
ASN1_V3_DATA = 0xa3,
};

class Asn1Parser
{
public:
Asn1Parser(const uint8_t* data, unsigned length) : buf(data), length(length)
{
}

unsigned getOffset() const
{
return offset;
}

void setOffset(unsigned offset)
{
this->offset = offset;
}

unsigned getLength()
{
if((buf[offset] & 0x80) == 0) {
return buf[offset++];
}

unsigned lengthBytes = buf[offset++] & 0x7f;
if(lengthBytes > 4) {
return 0;
}

uint32_t len = 0;
for(unsigned i = 0; i < lengthBytes; i++) {
len <<= 8;
len += buf[offset++];
}

return len;
}

// Skip the ASN1.1 object type and its length. Get ready to read the object's data.
unsigned getNextObject(uint8_t objType)
{
if(offset >= length || buf[offset] != objType) {
return 0;
}

++offset;
return getLength();
}

// Get the components of a distinguished name
uint8_t getObjectId()
{
auto len = getNextObject(ASN1_OID);
if(len == 0) {
return 0;
}

uint8_t dnType = 0;

/* expect a sequence of 2.5.4.[x] where x is a one of distinguished name
components we are interested in. */
if(len == 3 && buf[offset] == 0x55 && buf[offset + 1] == 0x04) {
dnType = buf[offset + 2];
}

// Skip it
offset += len;
return dnType;
}

// Extract a readable string
String getString()
{
auto asn1_type = buf[offset];

++offset;
auto len = getLength();

String s;
switch(asn1_type) {
case ASN1_UNICODE_STR:
len /= 2;
s.setLength(len);
for(unsigned i = 0; i < len; ++i) {
// Unicode MSB first
s[i] = buf[offset + 1];
offset += 2;
}
break;

case ASN1_PRINTABLE_STR:
case ASN1_PRINTABLE_STR2:
case ASN1_TELETEX_STR:
case ASN1_IA5_STR:
s.setString(reinterpret_cast<const char*>(&buf[offset]), len);
offset += len;
break;
}

return s;
}

private:
const uint8_t* buf;
unsigned length;
unsigned offset = 0;
};
37 changes: 37 additions & 0 deletions Sming/Components/ssl/BearSsl/BrCertificate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/SmingHub/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
*
* BrCertificate.cpp
*
****/

#include "BrCertificate.h"
#include <FlashString/Array.hpp>

namespace Ssl
{
String BrCertificate::getName(DN dn, RDN rdn) const
{
#define XX(tag, a, b, c, d) d,
DEFINE_FSTR_ARRAY_LOCAL(rdnTypes, uint8_t, SSL_X509_RDN_OID_MAP(XX));
#undef XX

uint8_t type = rdnTypes[unsigned(rdn)];
if(type == 0) {
return nullptr;
}

switch(dn) {
case DN::ISSUER:
return context->getIssuer().getRDN(type);
case DN::SUBJECT:
return context->getSubject().getRDN(type);
default:
return nullptr;
}
}

} // namespace Ssl
21 changes: 11 additions & 10 deletions Sming/Components/ssl/BearSsl/BrCertificate.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,39 @@
* http://github.com/SmingHub/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
*
* X509Context.h
*
* @author: 2019 - Slavey Karadzhov <[email protected]>
* BrCertificate.h
*
****/

#pragma once

#include <Network/Ssl/Certificate.h>
#include <Network/Ssl/Crypto.h>
#include "X509Context.h"

namespace Ssl
{
class BrCertificate : public Ssl::Certificate
{
public:
uint8_t sha1Hash[SHA1_SIZE];
BrCertificate(X509Context* context) : context(context)
{
}

bool matchFingerprint(const uint8_t* hash) const override
{
return memcmp(hash, sha1Hash, SHA1_SIZE) == 0;
return context->matchFingerprint(hash);
}

bool matchPki(const uint8_t* hash) const override
{
return false;
return context->matchPki(hash);
}

const String getName(Name name) const override
{
return nullptr;
}
String getName(DN dn, RDN rdn) const override;

private:
X509Context* context;
};

} // namespace Ssl
12 changes: 1 addition & 11 deletions Sming/Components/ssl/BearSsl/BrClientConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

/*
*/
#include "debug.h"
#include <SslDebug.h>
#include "BrClientConnection.h"
#include <Network/Ssl/Session.h>

Expand All @@ -38,14 +38,4 @@ int BrClientConnection::init()
return startHandshake();
}

const Certificate* BrClientConnection::getCertificate() const
{
if(certificate == nullptr) {
certificate = new BrCertificate();
x509Context->getCertificateHash(certificate->sha1Hash);
}

return certificate;
}

} // namespace Ssl
9 changes: 8 additions & 1 deletion Sming/Components/ssl/BearSsl/BrClientConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,14 @@ class BrClientConnection : public BrConnection

int init();

const Certificate* getCertificate() const override;
const Certificate* getCertificate() const override
{
if(certificate == nullptr) {
certificate = new BrCertificate(x509Context);
}

return certificate;
}

void freeCertificate() override
{
Expand Down
2 changes: 1 addition & 1 deletion Sming/Components/ssl/BearSsl/BrConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

/*
*/
#include "debug.h"
#include <SslDebug.h>
#include "BrConnection.h"
#include <Network/Ssl/Session.h>
#include <FlashString/Array.hpp>
Expand Down
2 changes: 1 addition & 1 deletion Sming/Components/ssl/BearSsl/BrServerConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

/*
*/
#include "debug.h"
#include <SslDebug.h>
#include "BrServerConnection.h"
#include <Network/Ssl/Session.h>

Expand Down
2 changes: 1 addition & 1 deletion Sming/Components/ssl/BearSsl/BrServerKey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*
****/

#include "debug.h"
#include <SslDebug.h>
#include "BrServerKey.h"

namespace Ssl
Expand Down
Loading

0 comments on commit 2de9d6b

Please sign in to comment.