Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSL validation using root cert crashes official HTTPSRequestCACertAxTLS example #6260

Closed
6 tasks done
nagimov opened this issue Jul 5, 2019 · 2 comments · Fixed by #6262
Closed
6 tasks done

SSL validation using root cert crashes official HTTPSRequestCACertAxTLS example #6260

nagimov opened this issue Jul 5, 2019 · 2 comments · Fixed by #6262

Comments

@nagimov
Copy link

nagimov commented Jul 5, 2019

Basic Infos

  • This issue complies with the issue POLICY doc.
  • I have read the documentation at readthedocs and the issue is not addressed there.
  • I have tested that the issue is present in current master branch (aka latest git).
  • I have searched the issue tracker for a similar issue.
  • If there is a stack dump, I have decoded it.
  • I have filled out all fields below.

Platform

  • Hardware: ESP8266EX
  • Core Version: 2.5.2
  • Development Env: Arduino IDE
  • Operating System: Ubuntu

Settings in IDE

  • Module: Nodemcu
  • Flash Mode: DOUT
  • Flash Size: 4MB
  • lwip Variant: v2 Lower Memory
  • Reset Method: ck
  • Flash Frequency: 40Mhz
  • CPU Frequency: 80Mhz
  • Upload Using: SERIAL (USB CH340 chip)
  • Upload Speed: 115200

Problem Description

Official example sketch HTTPSRequestCACertAxTLS.ino causes ESP to crash with exception on ssl_verify_cert().

Steps reproducing the issue:

  • git clone https://github.com/esp8266/Arduino
  • cd Arduino/libraries/ESP8266WiFi/examples/HTTPSRequestCACertAxTLS/
  • sed -i "s/your-ssid/my-ssid/" HTTPSRequestCACertAxTLS.ino
  • sed -i "s/your-password/my-password/" HTTPSRequestCACertAxTLS.ino
  • arduino HTTPSRequestCACertAxTLS.ino
  • upload sketch

Crashes with MWE as well (root certificate must be defined in CACert.ino):

MCVE Sketch

#define USING_AXTLS
#include <time.h>
#include <ESP8266WiFi.h>

#include <WiFiClientSecureAxTLS.h>
using namespace axTLS;

#ifndef STASSID
#define STASSID "my-ssid"
#define STAPSK  "my-password"
#endif

const char* ssid = STASSID;
const char* password = STAPSK;

const char* host = "api.github.com";
const int httpsPort = 443;

// Root certificate used by api.github.com.
// Defined in "CACert" tab.
extern const unsigned char caCert[] PROGMEM;
extern const unsigned int caCertLen;

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored  "-Wdeprecated-declarations"
WiFiClientSecure client;
#pragma GCC diagnostic pop

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }

  // Synchronize time useing SNTP
  configTime(8 * 3600, 0, "pool.ntp.org", "time.nist.gov");
  time_t now = time(nullptr);
  while (now < 8 * 3600 * 2) {
    delay(500);
    now = time(nullptr);
  }
  struct tm timeinfo;
  gmtime_r(&now, &timeinfo);

  // Load root certificate in DER format into WiFiClientSecure object
  bool res = client.setCACert_P(caCert, caCertLen);
  if (!res) {
    Serial.println("Failed to load root CA certificate!");
    while (true) {
      yield();
    }
  }
}

void loop() {
  if (!client.connect(host, httpsPort)) {
    Serial.println("connection failed");
    return;
  }
  Serial.println("connected");
  // Verify validity of server's certificate  <<<<==== crashes here
  if (client.verifyCertChain(host)) {
    Serial.println("Server certificate verified");
  } else {
    Serial.println("ERROR: certificate verification failed!");
    return;
  }
  Serial.println("verified");
}

Debug Messages

Stack trace from MWE:

connected

Exception (3):
epc1=0x4021b7ba epc2=0x00000000 epc3=0x00000000 excvaddr=0x4024bcee depc=0x00000000

>>>stack>>>

ctx: cont
sp: 3ffffd60 end: 3fffffc0 offset: 01a0
3fffff00:  5d1fa3e7 000c2c7f 3fffff20 3ffef564  
3fffff10:  3fff31ec 3fff0a14 3fff33c4 3fff03cc  
3fffff20:  3fffff60 3ffef734 3fff0a9c 40204aae  
3fffff30:  3ffe8616 00000000 3ffe8615 3ffee964  
3fffff40:  3ffee898 00000009 3ffee8fc 3ffee964  
3fffff50:  3ffee898 3fff0ed4 3ffef6c4 402196af  
3fffff60:  00000000 3ffee898 3ffe865b 402033bd  
3fffff70:  3ffe860d 3ffee898 3ffef6c4 4020270c  
3fffff80:  3ffe865b 0572528c 3ffee8fc 40203414  
3fffff90:  3ffee898 3ffe851c 3ffee8fc 4020114e  
3fffffa0:  3fffdad0 00000000 3ffee934 40203bf0  
3fffffb0:  feefeffe feefeffe 3ffe8554 40100459  
<<<stack<<<

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16 
tail 8
chksum 0x2d
csum 0x2d
v8b899c12
~ld

Decoded:

PC: 0x4021b7ba: x509_verify at ssl/x509.c line 437
EXCVADDR: 0x4024bcee

Decoding stack results
0x40204aae: uart_write(uart_t*, char const*, size_t) at /home/nagimov/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/uart.cpp line 498
0x402196af: ssl_verify_cert at ssl/tls1.c line 2101
0x402033bd: Print::write(char const*) at /home/nagimov/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/Print.h line 60
0x4020270c: axTLS::WiFiClientSecure::verifyCertChain(char const*) at /home/nagimov/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/libraries/ESP8266WiFi/src/include/SSLContext.h line 323
0x40203414: Print::println(char const*) at /home/nagimov/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/Print.cpp line 190
0x4020114e: loop() at /home/nagimov/esp/Arduino/libraries/ESP8266WiFi/examples/HTTPSRequestCACertAxTLS/HTTPSRequestCACertAxTLS.ino line 64
0x40203bf0: loop_wrapper() at /home/nagimov/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/cores/esp8266/core_esp8266_main.cpp line 125
@earlephilhower
Copy link
Collaborator

Axtls is relying on the non-32b aligned read exception handler in SDK3.0. But we had to move back to 2.2.x since pre3.0 :

#ifdef CONFIG_SSL_CERT_VERIFICATION
static const uint8_t sig_prefix_md5[] PROGMEM = {0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
static const uint8_t sig_prefix_sha1[] PROGMEM = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14};
static const uint8_t sig_prefix_sha256[] PROGMEM = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
static const uint8_t sig_prefix_sha384[] PROGMEM = {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
static const uint8_t sig_prefix_sha512[] PROGMEM = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};

/**
 * Take a signature and decrypt it.
 */
static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, uint8_t sig_type,
        bigint *modulus, bigint *pub_exp)
{
    int i;
    bigint *decrypted_bi, *dat_bi;
    bigint *bir = NULL;
    uint8_t *block = (uint8_t *)malloc(sig_len);

    const uint8_t *sig_prefix = NULL;
    uint8_t sig_prefix_size = 0, hash_len = 0;
    /* adjust our expections */
    switch (sig_type)
    {
        case SIG_TYPE_MD5:
            sig_prefix = sig_prefix_md5;
            sig_prefix_size = sizeof(sig_prefix_md5);
        break;
        case SIG_TYPE_SHA1:
....
        break;
    }
    if (sig_prefix)
        hash_len = sig_prefix[sig_prefix_size - 1];

So reading the last byte (to get the len) and set hash_len causes an exception.

earlephilhower added a commit to earlephilhower/Arduino that referenced this issue Jul 6, 2019
Fixes esp8266#6260.  AXTLS' x509 decode had a uncaught byte access to PROGMEM.
earlephilhower added a commit that referenced this issue Jul 6, 2019
Fixes #6260.  AXTLS' x509 decode had a uncaught byte access to PROGMEM.
@nagimov
Copy link
Author

nagimov commented Jul 8, 2019

Confirming working ok with current master branch. Awesome quick turnaround, thanks!

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants