HTTPS with AWS API Gateway [status:works, mostly]

There are any number of requests to integrate directly with the AWS API Gateway. I am in the midst of battle with the wolfssl library. You can find any number of library references.

There is a separate AWS API integration post which is good. This particular post shows how to hit the API to send data/message to the Photon. This particular effort is to push data from the Photon to AWS API (and into AWS Lambda). Don’t even think about getting directly to AWS Lambda. That is protected by the AWS IAM. In order to talk to AWS Lambda directly, you need to authenticate via Signature Version 4 methods. Once you do that, you can then do a direct call to AWS Lambda. By then, you will probably has spent out your 1MB allocation. :slight_smile:

It turns out access to the AWS API gateway for pushing information into is not so easy. I am at the point where I have to dig down into the source code and do some byte-wise comparisons of network traffic to get this to work. The tools are:

  • Native client example source code (client.c)
  • curl
  • Wireshark or tcpdump

The first thing to do is get a good representative example that works. This can be done quick and dirty on the command line using curl and supply the correct certs and arguments. Beyond that, actually testing the client is the next best thing to be sure the library can actually connect and do the TLS handshake.

Using a fairly stripped down library, I can get it to work with the AWS IoT service. However, the AWS API service is using more modern encryption methods which may prove too costly to implement.

Using curl, we find two interesting facts.

Fact #1

SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

According to the armMBED documentation, curl is using “RSA with Elliptic Curve Ephemeral Diffie Hellman (ECDHE-RSA) key exchange”.

Memory increase #1: Elliptical curve code needs to be turned on.

Fact #2

AWS API is using ALPN (Application Layer Protocol Negotiation). This is the slow march from HTTP/1.1 to HTTP/2 (aka h2). There are some good things that may come of this (read: What’s the Big Deal?).

Memory increase #2: ALPN has to be turned on and it also seems like SNI (Server Name Indication) also needs to be turned on.

I don’t know what else needs to happen, but between the two, I am now up against the 120k barrier with DEBUG code turned on. I am going to have to turn off debugging and error messages to keep the code small enough to get around some stack/heap errors that cause the Particle to panic and reset.

I figured I should write about this discovery as services move forward and upgrade software stacks. If things start breaking, this should give you an idea of where to begin looking.

wolfssl status

Curl

It turns out there are various components of several TLS libraries within curl which is probably why it works so well. It works better under Linux than MacOS. MacOS can’t seem to keep up with the pace of openssl. So, don’t do advanced testing under MacOS unless you’ve updated it via brew, etc. I personally use VirtualBox with a Linux VM on top of MacOS.

WolfSSL client

It also works under Linux. The relevant part of the debug output is this:

wolfSSL Entering SSL_new
wolfSSL Leaving SSL_new, return 0
ALPN accepted protocols list : h2
wolfSSL Entering wolfSSL_UseALPN
wolfSSL Entering TLSX_ALPN_New

In Particle, I’ve turned on ALPN and turned on the ECC curves. I can’t get the device to swing over into HTTP/2. Further down in the output, it does say it reached a match with ALPN, but I am still suffering from red light resets. Again, we may be hitting the limits on the firmware size.

Memory use: 
   text	   data	    bss	    dec	    hex	filename
 125140	    216	   2308	 127664	  1f2b0	/workspace/target/workspace.elf

Particle

wolfSSL Entering wolfSSL_CTX_set_verify
SNI is set.
Connected to gtem4845hl.execute-api.us-west-2.amazonaws.com
wolfSSL Entering SSL_new
wolfSSL Leaving SSL_new, return 0
SSL version is wolfSSL Entering SSL_get_version
TLSv1.2
wolfSSL Entering wolfSSL_UseALPN
wolfSSL Entering TLSX_ALPN_New
wolfSSL Entering TLSX_ALPN_New
ALPN settings were accepted.
No protocol match with peer -> Continue
ALPN_GetProtocol(-9)
Header size: 191
wolfSSL Entering SSL_write()
handshake not complete, trying to finish
wolfSSL Entering wolfSSL_negotiate
wolfSSL Entering SSL_connect()
Growing output buffer
Shrinking output buffer
connect state: CLIENT_HELLO_SENT
Growing input buffer
received record layer msg
wolfSSL Entering DoHandShakeMsg()
wolfSSL Entering DoHandShakeMsgType
processing server hello
SNI extension received
ALPN extension received
ALPN protocol match
wolfSSL Entering TLSX_ALPN_New

My fallback might be to take another look at axtls and mbedTLS.

Hello,

Let me ping someone that might be able to help, @rickkas7 are you able to assist?

Kyle

Thanks @KyleG ! Sorry for the fits and starts of projects all over the forum. They will all come together at some point.

Once recent discovery is the AWS API gateway will allow us to turn off ALPN negotiation so it can fall back to vanilla HTTP/1.1. However, there is no telling when this might be turned off for the stronger authentication methods.

I am able to get a response from the AWS API gateway using HTTP/1.1 or using ALPN under HTTP/1.1. The response is not the correct “expected” response. Under ALPN/h2 (HTTP/2), I do not get a response at all. I am seeing similar results using the library in a straight up Linux box.

I’ve also determined that the panics in the firmware are due to the Tom’s Fast Math library (apparently v0.10). My belief is that although it might be fast, it nests too deep causing a stack fault which is currently manifesting itself as a hard fault.

Anyone else attempting to look further at this port should not use this option:

#define USE_FAST_MATH

Investigation continues…

Alrighty… it works, but there is definitely a bug in the library to support ALPN;HTTP/2. Between this bug and a typo, there was quite a bit of head banging. :head_bandage:

At a minimum, you need ECC and SNI (server name indication) defined / turned on within the library to enable communication with AWS API (which then can hit a designated Lambda service). This will get into some documentation in a bit.

Permutations that are working:

  • No ALPN; HTTP/1.1 :heavy_check_mark:
  • ALPN; HTTP/1.1 :heavy_check_mark:
  • ALPN; HTTP/2 (also known as h2) :x:

This behavior is reproducible using the example client program under Linux.

Example session:

$ particle serial monitor --follow
Polling for available serial device...
Opening serial monitor for com port: "/dev/cu.usbmodem1421"
Serial monitor opened successfully:
Synced with time server.
SNI is set.
Connected to gtem4845hl.execute-api.us-west-2.amazonaws.com
SSL version is TLSv1.2
ALPN settings were accepted.
Header size: 180
ALPN(http/1.1)
sigCtx->state(0)
SIG_STATE_HASH sigOID(655)
SIG_STATE_KEY(keyOID:645)
RSAk: before mallocs
RSAk: after mallocs
SIG_STATE_DO(keyOID:645)
SIG_STATE_CHECK(keyOID:645)
sigCtx->state(0)
SIG_STATE_HASH sigOID(655)
SIG_STATE_KEY(keyOID:645)
RSAk: before mallocs
RSAk: after mallocs
SIG_STATE_DO(keyOID:645)
SIG_STATE_CHECK(keyOID:645)
Bytes written: 180
SSL cipher suite: NONE
client.available():128
Server response:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 46
Connection: keep-alive
Date: Wed, 09 Aug 2017 20:36:56 GMT
x-amzn-RequestId: 7c8761f0-7d42-11e7-9ced-1faaa19c2d6a
X-Trip: 0
X-Amzn-Trace-Id: sampled=0;root=1-598b7268-baf76b6f6925dc92a2550e8a
X-Cache: Miss from cloudfront
Via: 1.1 0f5c5f05c03169e6cc48b1a33dafb2d4.cloudfront.net (CloudFront)
X-Amz-Cf-Id: teElFnTdkHRU87uegoceazI1H2widwrkCGrFxDKa2DcFJypxV0PCgg==

You have reached the AWS API Lambda gateway...
Connection complete.

@cermak = Rockstar Coders status. :thumbsup:
Thanks for your continued digging with this library port.

wolfssl@0.0.2 is now published out to the Particle cloud. It should support AWS IoT and AWS API Gateway (using API Keys) services.

In both cases, you will need the Amazon CA certificate to install in the Private.h file. You can also place your API key in that file. I forgot to clean up the endpoint, so that will need to be changed from (prod/testParticle) to your endpoint. This has only been tested so far with the GET response. It should be trivial to update to a POST response and deliver a json payload or any payload via the BODY.

Until I can get more documentation in place, feel free to PM me or ask questions on the forum. I wanted to get some initial code out to @jimini for his project.

Caveats

The library now enables:

  • Server Name Indication and TLS extensions which add a meager 800 bytes to the firmware.
  • AWS API uses stronger encryption. The ECC (encryption curves) needed to be turned on before the server would talk to us. This adds 15k to the firmware size.

This version (0.0.2) of the library does not include APLN. If you need it, let me know. APLN will work with http/1.1, but not with h2. There seems to be a bug in the library. Using curl works fine with ALPN/h2.

3 Likes

@cermak,

I would like to introduce myself, I am the support captain for the wolfSSL organization. It was recently brought to my attention the number of topics discussing wolfSSL here in the particle forums and regretfully we were unaware at the time these questions were being asked.

I would like to say this is excellent work you have done in porting wolfSSL and my team and I are pleased to see you got wolfSSL + wolfMQTT working with AWS! I would officially like to extend an invitation to yourself and the particle community to contact us anytime via email at support [at] wolfssl [dot] com should you have questions about wolfSSL in the future!

I see you’ve found several of our optimization macros and while working with AWS you are limited by the cipher suites their servers support, but if you ever have a case where you control both ends of the connection there are configurations of wolfSSL that offer TLS functionality with builds under 30k. Obviously the available cipher suites are limited in such builds but something that can be considered for extremely constrained use-cases.

Our library is very modular in design and when a feature is not needed it can be disabled to free up room for other more interesting things!

Please let us know if you have any questions!

Warmest Regards,

Kaleb and the wolfSSL Team

4 Likes