NativeEthernet with x.509 cert

CeKl

New member
Hi everyone,

I have been trying for some time now to realize the following via the NativeEthernet-Libary and a Teensy 4.1 with the Ethernet-Kit:

The Teensy 4.1 regularly pings a web server via https GET request and receives a control command back. However, our computing center has given us the requirement to store an x.509 certificate on the Teensy so that the proxy server in the network forwards the request outside. Alternatively, if the whole thing is without a certificate, then an SSH connection is ok with them, but this would mean rewriting or creating a translate layer for the backend.

Now to my question:
Has anyone already gotten the NativeEthernet-Libary and a x.509 certificate to work? I last tried it with ArduinoBearSSL in the small demo below, but the Teensy fails when calling the connection (sslClient.connect()) and reboots.

If I can help with more information, feel free to ask!
Many thanks in advance!


Hardware:
  • Teensy 4.1
  • Ethernet-Kit (soldered and connected according to explanation; works without SSL)
Environment:
  • Arduino 2.3.3
  • Windows 11

C++:
#include <NativeEthernet.h>
#include <ArduinoBearSSL.h>


// Define the server and port
const char *server = "api.domain.com";  // Replace with your server's address
const int server_port = 443;              // HTTPS port


IPAddress ip(192, 168, 0, 100);
IPAddress myDns(192, 168, 0, 1);


const uint8_t root_ca_der[] = {
  0x30, 0x82, 0x06, 0x03, 0x30, 0x82, 0x03, 0xeb, 0xa0, 0x03, 0x02, 0x01,
    ....
  0xb9, 0x5f, 0x49, 0xba, 0x56, 0xb0, 0x9b
};

const size_t root_ca_der_len = 1543;

EthernetClient ethClient;
BearSSLClient sslClient(ethClient);

byte mac[] = {};

unsigned long beginMicros, endMicros;
unsigned long byteCount = 0;
bool printWebData = true;


void teensyMAC(uint8_t *mac) {
  for (uint8_t by = 0; by < 2; by++) mac[by] = (HW_OCOTP_MAC1 >> ((1 - by) * 8)) & 0xFF;
  for (uint8_t by = 0; by < 4; by++) mac[by + 2] = (HW_OCOTP_MAC0 >> ((3 - by) * 8)) & 0xFF;
  Serial.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}


void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  teensyMAC(mac);

  Serial.println("Initialize Ethernet with DHCP:");
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");

    // Check for Ethernet hardware present
    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
      Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
      while (true) {
        delay(1);  // do nothing, no point running without Ethernet hardware
      }
    }
    if (Ethernet.linkStatus() == LinkOFF) {
      Serial.println("Ethernet cable is not connected.");
    }

    // try to congifure using IP address instead of DHCP:
    Ethernet.begin(mac, ip, myDns);
  } else {
    Serial.print("  DHCP assigned IP ");
    Serial.println(Ethernet.localIP());
  }


  // give a second to initialize:
  delay(1000);
  Serial.print("connecting to ");
  Serial.print(server);
  Serial.println("...");

  // CreateBearSSL certificate object
  br_x509_certificate root_ca_cert;
  memset(&root_ca_cert, 0, sizeof(root_ca_cert));
  root_ca_cert.data = (unsigned char *)root_ca_der;
  root_ca_cert.data_len = root_ca_der_len;

  sslClient.setEccCert(root_ca_cert);

  // Send an HTTPS GET request
  if (sslClient.connect(server, server_port)) {
    sslClient.println("GET /status HTTP/1.1");
    sslClient.print("Host: ");
    sslClient.println(server);
    sslClient.println("Connection: close");
    sslClient.println();
  } else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }
  beginMicros = micros();

}

void loop() {

  // if there are incoming bytes available
  // from the server, read them and print them:
  int len = sslClient.available();
  if (len > 0) {
    byte buffer[80];
    if (len > 80) len = 80;
    sslClient.read(buffer, len);
    if (printWebData) {
      Serial.write(buffer, len);  // show in the serial monitor (slows some boards)
    }
    byteCount = byteCount + len;
  }

  // if the server's disconnected, stop the client:
  if (!sslClient.connected()) {
    endMicros = micros();
    Serial.println();
    Serial.println("disconnecting.");
    sslClient.stop();
    Serial.print("Received ");
    Serial.print(byteCount);
    Serial.print(" bytes in ");
    float seconds = (float)(endMicros - beginMicros) / 1000000.0;
    Serial.print(seconds, 4);
    float rate = (float)byteCount / seconds / 1000.0;
    Serial.print(", rate = ");
    Serial.print(rate);
    Serial.print(" kbytes/second");
    Serial.println();

    // do nothing forevermore:
    while (true) {
      delay(1);
    }
  }
}
 
I am not an Ethernet expert, but you should try using QNEthernet instead.
It would appear that NativeEthernet is no longer maintained, whilst QNEthernet is actively maintained.
 
QNEthernet has support for Mbed TLS 2.x. There’s an MbedTLSDemo example. However, the use is a little complex, so I’m thinking about how to incorporate v3.x and how to simplify its use. No promises on any sort of timeline.
 
Back
Top