SSL with Wifi101 on Adafruit Feather M0 not working on specific site

Hi! After updating the root certificates on my Feather M0 using the firmware updater, I was able to run the Google WifiSSL example sketch just fine.

However try as I might I cannot connect to https://bustime.norta.com even after uploading the root cert to the M0. I've tried connecting via IP address instead of DNS, using BearSSL, and even connecting to my phone's hotspot in case something weird was being blocked on my router.

Weirdly going to bustime.norta.com on a browser does not redirect you to https://norta.bustime.com - it just hangs there forever? I've also had some weird issues pinging the site. A part of me wonders if it's not even uploading the root cert to the board properly because if I can't even ping bustime.norta.com I find it hard to believe the IDE is downloading the cert.

Any guidance here would greatly be appreciated! Below is my code just in case you want to check anything. I'm tempted to try this on an ESP32 to see if anything else happens but the fact that Google works and Norta won't doesn't give me much confidence that the board is the issue.

/*
This example creates a client object that connects and transfers
data using always SSL.

It is compatible with the methods normally related to plain
connections, like client.connect(host, port).

Written by Arturo Guadalupi
last revision November 2015

*/

#include <SPI.h>
#include <WiFi101.h>


#include "arduino_secrets.h" 
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;            // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;

// Examples - both work 
//IPAddress server(142, 250, 189, 196);  // numeric IP for Google (no DNS) (updated as demo seemed to be wrong)(also does it need spaces?? demo didn't have spaces)
//char server[] = "www.google.com";    // name address for Google (using DNS)

//bustime attempts - neither work   
char server[] = "bustime.norta.com";   
//IPAddress server(142,190,113,10);  

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
WiFiSSLClient client;

/* this is the downloaded cert but I have no idea how to utilize this with wifi101 or if it would even make a difference 

-----BEGIN CERTIFICATE-----
MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
WD9f
-----END CERTIFICATE-----

*/


void setup() {
  WiFi.setPins(8, 7, 4, 2);  //don't forget this
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }

  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(3000);
  }
  Serial.println("Connected to wifi");
  printWiFiStatus();

// example
/*

  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  if (client.connectSSL(server, 443)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.println("GET /search?q=arduino HTTP/1.1");
    client.println("Host: www.google.com");
    client.println("Connection: close");
    client.println();
  } else {
    Serial.println("that didn't work either");
  }
  */

// norta bustime

  Serial.print("\nStarting connection to server...");
  Serial.println(server);
  // if you get a connection, report back via serial:
  if (client.connectSSL(server, 443)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.println("GET bustime/home.jsp HTTP/1.1");
    client.println("Host: bustime.norta.com");
    client.println("Connection: close");
    client.println();
  } else {
    Serial.println("that didn't work either");
  }

}

void loop() {
  // if there are incoming bytes available
  // from the server, read them and print them:
  while (client.available()) {
    char c = client.read();
    Serial.write(c);
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting from server.");
    client.stop();

    // do nothing forevermore:
    while (true);
  }
}


void printWiFiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

Ooook so going to norta.bustime.com:443 in my browser gives you an error:

Bad Request
This combination of host and port requires TLS.

I'm guessing that's it? Either the cert isn't being uploaded to the board or the request is just being rejected outright.

Any advice?

The URI in the request-line after the method verb always starts with a slash

    client.println("GET /bustime/home.jsp HTTP/1.1");

Without it, I was getting HTTP 400; adding it made it work on a UNO R4 WiFi. Of course, you have to connect first.

bustime.norta.com depends on the "GlobalSign Root CA - R3" certificate. It is one of the 146 certificates in the current R4 firmware. What you have commented out in your code seems to match.

From what I can tell, WiFi101 only has room for about 10 certs. A brief search did not reveal which ones are in the firmware by default. Apparently, one uses the Firmware Updater to specify which site(s) you want to use and it will go to there to determine the root(s) and save those. (The screenshot there shows google.com as one of four, so that's why it works.) There is no way to use the cert directly, as there is with ESP32.

Redirecting is a courtesy, not a requirement. Browsers have started doing HTTPS-First, which is a good idea; so lack of redirect is less of a problem. Hanging instead of unreachable or refused....

Thank you so much for this! So you were successfully able to connect? I did use the firmware updater to add a cert for bustime.norta.com but I am still unable to connect.

If you were indeed able to get the code working on an UNO R4 WiFi then I will just try a different board.

Yes, I was able to connect.

For the WiFi101, you could also try adding another popular site like amazon.com; or removing google.com to see if it still works after. Does the Updater actually do what it says.

That's a good idea - I will try removing the Google cert and see what happens. Will report back!

OK after removing the google cert I could not connect to Google via SSL. So the firmware updater IS working at least as far as the Google cert is concerned.

Edit: and to be specific I did have like 8 certs uploaded for various sites and removed them all.

Found an 8-year-old Adafruit fork of the Firmware Updater

with the original dozen or so certs that were hard-coded. It's written in Go, and depends on an old version of a serial library. To pin a dependency on a specific commit, you need to use a Go module; and since I went to trouble of figuring out which version, I might as well write it down

$ cd src/github.com/arduino-libraries/WiFi101-FirmwareUpdater
$ go mod init github.com/arduino-libraries/WiFi101-FirmwareUpdater
$ go get go.bug.st/serial@2cc8858
$ go build cli/main/winc1500-uploader.go
$ ./winc1500-uploader --help
Usage of ./winc1500-uploader:
  -address value
        address (host:port) to fetch and flash root certificate for, multiple values allowed
  -certs string
        root certificate directory
  -firmware string
        firmware file to flash
  -port string
        serial port to use for flashing
  -read
        read all firmware and output to stdout

Don't use the -certs flag -- they have all expired. Instead, specify individual hosts to fetch. If you don't have Go, are not on Linux, and feeling lucky, there are precompiled Mac and Windows binaries checked in.

Again, that is a fork of a currently maintained repo

which has binaries for all platforms with its releases. The really old one or a current one might work better than the other. The GUI I linked before is a plugin for the 1.x IDE. Both are written in Java.

Between the old Go, the current Go, and the Java, one might show -- or could be modified to show -- what is actually going on, to explain why your site is not working.

So I borrowed a TinyPico from a friend and indeed was able to connect properly - thus proving that neither of us are crazy.

I am sort of boggled at this point but I don't think I'm the only one having issues with this method/board/library. I'm going to try to do as you suggest because now I'm curious and I'm in touch with Adafruit now. I so appreciate your help - going to mark this as solved and if I figure out a concrete answer I will come back and update this thread.