This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

changing certificate in https_client sample

I am trying the https_client sample and I can get it to work unchanged. 

But I would like to connect to a different site than www.example.com. 

As far as I can understand what I need to do is:

change "example.com" in the HTTP_HEAD to another site (i've tried "vecka.nu")

#define HTTP_HEAD                                                              \
	"HEAD / HTTP/1.1\r\n"                                                  \
	"Host: vecka.nu:443\r\n"                                            \
	"Connection: close\r\n\r\n"

change "example.com" in the gettaddrinfo() call to another site (i've tried "vecka.nu"

	err = getaddrinfo("vecka.nu", NULL, &hints, &res);
	if (err) {
		printk("getaddrinfo() failed, err %d\n", errno);
		return;
	}

change the certificate used to one that works with the new site:

static const char cert[] = {
	//#include "../cert/DigiCertGlobalRootCA.pem"
	#include "../cert/vecka.cer"
};

I got the new certificate by visiting www.vecka.nu in chrome,

  • clicking the lock to the left of the address bar,
  • selecting certificate
  • going to the Details tab
  • clicking the Copy to File... button
  • selecting Base-64 encoded x.509 (.CER)
  • saving the file in the cert folder of the https_client sample
  • adding " to the beginning of each line and \n" to the end of each line in the new .cer file

"-----BEGIN CERTIFICATE-----\n"
"MIIFIzCCBAugAwIBAgISBDyCXR6TuWHUHlrrOBfKHRrQMA0GCSqGSIb3DQEBCwUA\n"
"MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD\n"

...
...

"DqGgSg+/716RXuzlHZqyb8pqU0cTTq2ojWgLx1FdDyfVcXGU6jOSeQ4WG2d8KJQ1\n"
"f0FUcInSAoWkuB8oWMFepQQxAxDdfj0=\n"
"-----END CERTIFICATE-----\n"

When I do this I get this output:

*** Booting Zephyr OS build v2.6.0-rc1-ncs1  ***
HTTPS client sample started
Provisioning certificate
Waiting for network.. OK
Connecting to example.com
connect() failed, err: 111

I also followed the same procedure to download the certificate from www.example.com in chrome, and noticed that the certificate did not match the certificate that came with the sample, so I suspect that I am not using the correct certificate.

How should I obtain the certificate for different websites?

  • Hello,

     

    The whole certificate chain can be fetched using openssl (also from your browser as you did):

    openssl s_client -showcerts -connect vecka.nu:443 -tls1_2

     

    It seems that you have found a bug in this specific sample, when we added SNI support in our modem fw, we forgot to specify the TLS_HOSTNAME (SNI requirement).

    Can you try to add this in tls_setup() function and see if it starts working?

    	err = setsockopt(fd, SOL_TLS, TLS_HOSTNAME, "vecka.nu", sizeof("vecka.nu"));
    	if (err) {
    		printk("Failed to setup TLS sec tag, err %d\n", errno);
    		return err;
    	}

     

    Kind regards,

    Håkon

  • Oh no, just wasted hours in finding a bug in my source (based on https_client); for me, the error with my server (nextcloud , others IIS based) setup was ECONNRESET 104   (note, some other servers worked so far, I guess 50% affected);

    ** BUT **

    There is a corresponding  issue with the download sample  ( path  \nrf\samples\nrf9160\download  )!!! there is a flag now required:

    static struct download_client_cfg config = {
    #if CONFIG_SAMPLE_SECURE_SOCKET
    .sec_tag = SEC_TAG,
    .set_tls_hostname = true,

    This fixed the connection issue. unfortunately for me, the next issue is with huge headers in the http response, so the waste of time continues.

  •  FYI with the huge headers, it seems like

     CONFIG_DOWNLOAD_CLIENT_HTTP_FRAG_SIZE_1024=y

    helped with some of my servers, but not yet with my preferred server (nextcloud,nginx), it just sends too much garbage headers, plus uses alias download URLs, not the real filename (which can only be found in the respons  by a Content-Disposition header). 

  • Hello,

    I tried copying the setsockopt into the tls_setup() as you said, but I still got the same error

    int tls_setup(int fd)
    {
    	int err;
    	int verify;
    
    	/* Security tag that we have provisioned the certificate with */
    	const sec_tag_t tls_sec_tag[] = {
    		TLS_SEC_TAG,
    	};
    
    	/* Set up TLS peer verification */
    	enum {
    		NONE = 0,
    		OPTIONAL = 1,
    		REQUIRED = 2,
    	};
    
    	verify = REQUIRED;
    
    	err = setsockopt(fd, SOL_TLS, TLS_HOSTNAME, "vecka.nu", sizeof("vecka.nu"));
    	if (err) {
    		printk("Failed to setup TLS sec tag, err %d\n", errno);
    		return err;
    	}
    
    	err = setsockopt(fd, SOL_TLS, TLS_PEER_VERIFY, &verify, sizeof(verify));
    	if (err) {
    		printk("Failed to setup peer verification, err %d\n", errno);
    		return err;
    	}
    
    	/* Associate the socket with the security tag
    	 * we have provisioned the certificate with.
    	 */
    	err = setsockopt(fd, SOL_TLS, TLS_SEC_TAG_LIST, tls_sec_tag,
    			 sizeof(tls_sec_tag));
    	if (err) {
    		printk("Failed to setup TLS sec tag, err %d\n", errno);
    		return err;
    	}
    	return 0;
    }

    *** Booting Zephyr OS build v2.6.0-rc1-ncs1  ***
    HTTPS client sample started
    Provisioning certificate
    Waiting for network.. OK
    Connecting to example.com
    connect() failed, err: 111

    Thank you for the terminal command, it is much simpler than using a web browser.

    //Anna

  • Hi Anna,

     

    diff --git a/samples/nrf9160/https_client/src/main.c b/samples/nrf9160/https_client/src/main.c
    index 509aacb96..7f85fd630 100644
    --- a/samples/nrf9160/https_client/src/main.c
    +++ b/samples/nrf9160/https_client/src/main.c
    @@ -17,9 +17,11 @@
     
     #define HTTPS_PORT 443
     
    +#define HTTPS_HOSTNAME "vecka.nu"
    +
     #define HTTP_HEAD                                                              \
     	"HEAD / HTTP/1.1\r\n"                                                  \
    -	"Host: example.com:443\r\n"                                            \
    +	"Host: " HTTPS_HOSTNAME ":443\r\n"                                     \
     	"Connection: close\r\n\r\n"
     
     #define HTTP_HEAD_LEN (sizeof(HTTP_HEAD) - 1)
    @@ -34,7 +36,7 @@ static char recv_buf[RECV_BUF_SIZE];
     
     /* Certificate for `example.com` */
     static const char cert[] = {
    -	#include "../cert/DigiCertGlobalRootCA.pem"
    +	#include "../cert/lets-encrypt-r3"
     };
     
     BUILD_ASSERT(sizeof(cert) < KB(4), "Certificate too large");
    @@ -137,6 +139,11 @@ int tls_setup(int fd)
     		return err;
     	}
     
    +	err = setsockopt(fd, SOL_TLS, TLS_HOSTNAME, HTTPS_HOSTNAME, sizeof(HTTPS_HOSTNAME) - 1);
    +	if (err) {
    +		printk("Failed to setup TLS hostname, err %d\n", errno);
    +		return err;
    +	}
     	return 0;
     }
     
    @@ -181,7 +188,7 @@ void main(void)
     	}
     	printk("OK\n");
     
    -	err = getaddrinfo("example.com", NULL, &hints, &res);
    +	err = getaddrinfo(HTTPS_HOSTNAME, NULL, &hints, &res);
     	if (err) {
     		printk("getaddrinfo() failed, err %d\n", errno);
     		return;
    @@ -201,7 +208,7 @@ void main(void)
     		goto clean_up;
     	}
     
    -	printk("Connecting to %s\n", "example.com");
    +	printk("Connecting to %s\n", HTTPS_HOSTNAME);
     	err = connect(fd, res->ai_addr, sizeof(struct sockaddr_in));
     	if (err) {
     		printk("connect() failed, err: %d\n", errno);
    

     

    And here's the lets-encrypt-r3 (signed by X1) in C form:

    "-----BEGIN CERTIFICATE-----\n" \
    "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\n" \
    "nLRbwHOoq7hHwg==\n" \
    "-----END CERTIFICATE-----\n"

     

    And here's the output at my end:

    HTTPS client sample started
    Provisioning certificate
    Waiting for network.. OK
    Connecting to vecka.nu
    Sent 58 bytes
    Received 367 bytes
    
    >        HTTP/1.1 200 OK
    
    Finished, closing socket.
    

     

    Note: you need mfw v1.2.3 or newer for SNI to work.

     

    Kind regards,

    Håkon

Related