2

I'm trying to make a request to an ip using RPi pico w, using the picohttps example provided in here.

Now for that we have 3 needed parameters in picohttps.h file - SSID, SSID_Password, PICOHTTPS_CA_ROOT_CERT. I've filled first two, but couldn't understand what to write here. I know about RootCA cert little bit, but what part to write here? Whole certificate?

Any other working example for http request using pico c-sdk would be great also.

https://github.com/marceloalcocer/picohttps

Here(pichohttps.h) - ???

#define PICOHTTPS_CA_ROOT_CERT                          \
{                                                       \
    0x03, 0x3a, 0xf1, 0xe6, 0xa7, 0x11, 0xa9, 0xa0,     \
    0xbb, 0x28, 0x64, 0xb1, 0x1d, 0x09, 0xfa, 0xe5      \
}

I've attached my code as of now.

picohttps.h

/* Pico HTTPS request example *************************************************
 *                                                                            *
 *  An HTTPS client example for the Raspberry Pi Pico W                       *
 *                                                                            *
 *  A simple yet complete example C application which sends a single request  *
 *  to a web server over HTTPS and reads the resulting response.              *
 *                                                                            *
 ******************************************************************************/

#ifndef PICOHTTPS_H
#define PICOHTTPS_H



/* Options ********************************************************************/

// Wireless region
//
//  `country` argument to cyw43_arch_init_with_country().
//
//  For best performance, set to local region.
//
//  https://www.raspberrypi.com/documentation/pico-sdk/networking.html#CYW43_COUNTRY_
//
#define PICOHTTPS_INIT_CYW43_COUNTRY                CYW43_COUNTRY_INDIA

// Wireless network SSID
#define PICOHTTPS_WIFI_SSID                         "mywifi"

// Wireless network connection timeout
//
//  `timeout` argument to cyw43_arch_wifi_connect_timeout_ms().
//
//  https://www.raspberrypi.com/documentation/pico-sdk/networking.html
//
#define PICOHTTPS_WIFI_TIMEOUT                      20000           // ms

// Wireless network password
//
//  N.b. _Strongly_ recommend setting this from the environment rather than
//  here. Environment values will have greater precedence. See CMakeLists.txt.
//
// #ifndef PICOHTTPS_WIFI_PASSWORD
#define PICOHTTPS_WIFI_PASSWORD                     "password"
// #endif // PICOHTTPS_WIFI_PASSWORD

// HTTP server hostname
#define PICOHTTPS_HOSTNAME                          "example.edu"

// DNS response polling interval
//
//  Interval with which to poll for responses to DNS queries.
//
#define PICOHTTPS_RESOLVE_POLL_INTERVAL             100             // ms

// Certificate authority root certificate
//
//  CA root certificate used to sign the HTTP server's certificate (DER
//  format, char array representation).
//
//  This is most readily obtained via inspection of the server's certificate
//  chain, e.g. in a browser.
//
// #define PICOHTTPS_CA_ROOT_CERT                          
// {                                                       
//     0x03, 0x3a, 0xf1, 0xe6, 0xa7, 0x11, 0xa9, 0xa0,     
//     0xbb, 0x28, 0x64, 0xb1, 0x1d, 0x09, 0xfa, 0xe5      

// }

#define PICOHTTPS_CA_ROOT_CERT                          \
{                                                       \
    0x03, 0x3a, 0xf1, 0xe6, 0xa7, 0x11, 0xa9, 0xa0,     \
    0xbb, 0x28, 0x64, 0xb1, 0x1d, 0x09, 0xfa, 0xe5      \
}

// 07:5B:CE:F3:06:89:C8:AD:
// DF:13:E5:1A:F4:AF:E1:87

// 03:3A:F1:E6:A7:11:A9:A0:
// BB:28:64:B1:1D:09:FA:E5




// TCP + TLS connection establishment polling interval
//
//  Interval with which to poll for establishment of TCP + TLS connection
//
#define PICOHTTPS_ALTCP_CONNECT_POLL_INTERVAL       100             // ms

// TCP + TLS idle connection polling interval
//
//  Interval with which to poll application (i.e. call registered polling
//  callback function) when TCP + TLS connection is idle.
//
//  The callback function should be registered with altcp_poll(). The polling
//  interval is given in units of 'coarse grain timer shots'; one shot
//  corresponds to approximately 500 ms.
//
//  https://www.nongnu.org/lwip/2_1_x/group__altcp.html
//
#define PICOHTTPS_ALTCP_IDLE_POLL_INTERVAL          2               // shots

// HTTP request
//
//  Plain-text HTTP request to send to server
//
#define PICOHTTPS_REQUEST                   \
    "GET / HTTP/1.1\r\n"                    \
    "Host: " PICOHTTPS_HOSTNAME "\r\n"      \
    "\r\n"


// HTTP response polling interval
//
//  Interval with which to poll for HTTP response from server.
//
#define PICOHTTPS_HTTP_RESPONSE_POLL_INTERVAL       100             // ms



/* Macros *********************************************************************/

// Array length
#define LEN(array) (sizeof array)/(sizeof array[0])



/* Data structures ************************************************************/

// lwIP errors
//
//  typedef here to make source of error code more explicit
//
typedef err_t lwip_err_t;

// TCP connection callback argument
//
//  All callbacks associated with lwIP TCP (+ TLS) connections can be passed a
//  common argument. This is intended to allow application state to be accessed
//  from within the callback context. The argument should be registered with
//  altcp_arg().
//
//  The following structure is used for this argument in order to supply all
//  the relevant application state required by the various callbacks.
//
//  https://www.nongnu.org/lwip/2_1_x/group__altcp.html
//
struct altcp_callback_arg{

    // TCP + TLS connection configurtaion
    //
    //  Memory allocated to the connection configuration structure needs to be
    //  freed (with altcp_tls_free_config) in the connection error callback
    //  (callback_altcp_err).
    //
    //  https://www.nongnu.org/lwip/2_1_x/group__altcp.html
    //  https://www.nongnu.org/lwip/2_1_x/group__altcp__tls.html
    //
    struct altcp_tls_config* config;

    // TCP + TLS connection state
    //
    //  Successful establishment of a connection needs to be signaled to the
    //  application from the connection connect callback
    //  (callback_altcp_connect).
    //
    //  https://www.nongnu.org/lwip/2_1_x/group__altcp.html
    //
    bool connected;

    // Data reception acknowledgement
    //
    //  The amount of data acknowledged as received by the server needs to be
    //  communicated to the application from the connection sent callback
    //  (callback_altcp_sent) for validatation of successful transmission.
    //
    u16_t acknowledged;

};



/* Functions ******************************************************************/

// Initialise standard I/O over USB
//
//  @return         `true` on success
//
bool init_stdio(void);

// Initialise Pico W wireless hardware
//
//  @return         `true` on success
//
bool init_cyw43(void);

// Connect to wireless network
//
//  @return         `true` on success
//
bool connect_to_network(void);

// Resolve hostname
//
//  @param ipaddr   Pointer to an `ip_addr_t` where the resolved IP address
//                  should be stored.
//
//  @return         `true` on success
//
bool resolve_hostname(ip_addr_t* ipaddr);

// Free TCP + TLS protocol control block
//
//  Memory allocated for a protocol control block (with altcp_tls_new) needs to
//  be freed (with altcp_close).
//
//  @param pcb      Pointer to a `altcp_pcb` structure to be freed
//
void altcp_free_pcb(struct altcp_pcb* pcb);

// Free TCP + TLS connection configuration
//
//  Memory allocated for TCP + TLS connection configuration (with
//  altcp_tls_create_config_client) needs to be freed (with
//  altcp_tls_free_config).
//
//  @param config   Pointer to a `altcp_tls_config` structure to be freed
//
void altcp_free_config(struct altcp_tls_config* config);

// Free TCP + TLS connection callback argument
//
//  The common argument passed to lwIP connection callbacks must remain in
//  scope for the duration of all callback contexts (i.e. connection lifetime).
//  As such, it cannot be declared with function scope when registering the
//  callback, but rather should be allocated on the heap. This implies the
//  allocated memory must be freed on connection close.
//
//  @param arg      Pointer to a `altcp_callback_arg` structure to be freed
//
void altcp_free_arg(struct altcp_callback_arg* arg);

// Establish TCP + TLS connection with server
//
//  @param ipaddr   Pointer to an `ip_addr_t` containing the server's IP
//                  address
//  @param pcb      Double pointer to a `altcp_pcb` structure where the
//                  protocol control block for the established connection
//                  should be stored.
//
//  @return         `true` on success
//
bool connect_to_host(ip_addr_t* ipaddr, struct altcp_pcb** pcb);

// Send HTTP request
//
//  @param pcb      Pointer to a `altcp_pcb` structure containing the TCP + TLS
//                  connection PCB to the server.
//
//  @return         `true` on success
//
bool send_request(struct altcp_pcb* pcb);

// DNS response callback
//
//  Callback function fired on DNS query response.
//
//  Registered with dns_gethostbyname().
//
//  https://www.nongnu.org/lwip/2_1_x/group__dns.html
//
void callback_gethostbyname(
    const char* name,
    const ip_addr_t* resolved,
    void* ipaddr
);

// TCP + TLS connection error callback
//
//  Callback function fired on TCP + TLS connection fatal error.
//
//  Registered with altcp_err().
//
//  https://www.nongnu.org/lwip/2_1_x/group__altcp.html
//
void callback_altcp_err(void* arg, lwip_err_t err);

// TCP + TLS connection idle callback
//
//  Callback function fired on idle TCP + TLS connection.
//
//  Registered with altcp_err().
//
//  https://www.nongnu.org/lwip/2_1_x/group__altcp.html
//
lwip_err_t callback_altcp_poll(void* arg, struct altcp_pcb* pcb);

// TCP + TLS data acknowledgement callback
//
//  Callback function fired on acknowledgement of data reception by server over
//  a TCP + TLS connection.
//
//  Registered with altcp_sent().
//
//  https://www.nongnu.org/lwip/2_1_x/group__altcp.html
//
lwip_err_t callback_altcp_sent(void* arg, struct altcp_pcb* pcb, u16_t len);

// TCP + TLS data reception callback
//
//  Callback function fired on reception of data from server over a TCP +
//  TLS connection.
//
//  Registered with altcp_recv().
//
//  https://www.nongnu.org/lwip/2_1_x/group__altcp.html
//
lwip_err_t callback_altcp_recv(
    void* arg,
    struct altcp_pcb* pcb,
    struct pbuf* buf,
    lwip_err_t err
);

// TCP + TLS connection establishment callback
//
//  Callback function fired on successful establishment of TCP + TLS connection.
//
//  Registered with altcp_connect().
//
//  https://www.nongnu.org/lwip/2_1_x/group__altcp.html
//
lwip_err_t callback_altcp_connect(
    void* arg,
    struct altcp_pcb* pcb,
    lwip_err_t err
);

#endif //PICOHTTPS_H

1 Answer 1

1

The comment:

//  CA root certificate used to sign the HTTP server's certificate (DER
//  format, char array representation).

is saying that you need to find the Root CA certificate that was used to sign the chain of certificates that signed the certificate used by the HTTPS server.

For raspberrypi.stackexchange.com, this is the certificate called "ISRG Root X2" highlighted in grey below.

enter image description here

This certificate needs to be in DER (binary) format. Unfortunately, Chrome doesn't have an option to export the certificate in DER format. After exporting from Chrome I had to use the following OPENssl command to convert the certificate to DER/binary:

openssl x509 -outform der -in "ISRG Root X2" -out "ISRG Root X2.der"

Then use xxd -i to convert the binary DER file to character array format and paste the character array into your header file.

xxd -i ISRG\ Root\ X2.der 
unsigned char ISRG_Root_X2_der[] = {
  0x30, 0x82, 0x02, 0x1b, 0x30, 0x82, 0x01, 0xa1, 0xa0, 0x03, 0x02, 0x01,
  0x02, 0x02, 0x10, 0x41, 0xd2, 0x9d, 0xd1, 0x72, 0xea, 0xee, 0xa7, 0x80,
  0xc1, 0x2c, 0x6c, 0xe9, 0x2f, 0x87, 0x52, 0x30, 0x0a, 0x06, 0x08, 0x2a,
  0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x4f, 0x31, 0x0b, 0x30,
  0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x29,
  0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x20, 0x49, 0x6e, 0x74,
  0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69,
  0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20,
  0x47, 0x72, 0x6f, 0x75, 0x70, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55,
  0x04, 0x03, 0x13, 0x0c, 0x49, 0x53, 0x52, 0x47, 0x20, 0x52, 0x6f, 0x6f,
  0x74, 0x20, 0x58, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x30, 0x30, 0x39,
  0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x34,
  0x30, 0x30, 0x39, 0x31, 0x37, 0x31, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a,
  0x30, 0x4f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
  0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0a,
  0x13, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x53,
  0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65,
  0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x31, 0x15,
  0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0c, 0x49, 0x53, 0x52,
  0x47, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x58, 0x32, 0x30, 0x76, 0x30,
  0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05,
  0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xcd, 0x9b, 0xd5,
  0x9f, 0x80, 0x83, 0x0a, 0xec, 0x09, 0x4a, 0xf3, 0x16, 0x4a, 0x3e, 0x5c,
  0xcf, 0x77, 0xac, 0xde, 0x67, 0x05, 0x0d, 0x1d, 0x07, 0xb6, 0xdc, 0x16,
  0xfb, 0x5a, 0x8b, 0x14, 0xdb, 0xe2, 0x71, 0x60, 0xc4, 0xba, 0x45, 0x95,
  0x11, 0x89, 0x8e, 0xea, 0x06, 0xdf, 0xf7, 0x2a, 0x16, 0x1c, 0xa4, 0xb9,
  0xc5, 0xc5, 0x32, 0xe0, 0x03, 0xe0, 0x1e, 0x82, 0x18, 0x38, 0x8b, 0xd7,
  0x45, 0xd8, 0x0a, 0x6a, 0x6e, 0xe6, 0x00, 0x77, 0xfb, 0x02, 0x51, 0x7d,
  0x22, 0xd8, 0x0a, 0x6e, 0x9a, 0x5b, 0x77, 0xdf, 0xf0, 0xfa, 0x41, 0xec,
  0x39, 0xdc, 0x75, 0xca, 0x68, 0x07, 0x0c, 0x1f, 0xea, 0xa3, 0x42, 0x30,
  0x40, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04,
  0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13,
  0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d,
  0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x7c, 0x42, 0x96,
  0xae, 0xde, 0x4b, 0x48, 0x3b, 0xfa, 0x92, 0xf8, 0x9e, 0x8c, 0xcf, 0x6d,
  0x8b, 0xa9, 0x72, 0x37, 0x95, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48,
  0xce, 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x30,
  0x7b, 0x79, 0x4e, 0x46, 0x50, 0x84, 0xc2, 0x44, 0x87, 0x46, 0x1b, 0x45,
  0x70, 0xff, 0x58, 0x99, 0xde, 0xf4, 0xfd, 0xa4, 0xd2, 0x55, 0xa6, 0x20,
  0x2d, 0x74, 0xd6, 0x34, 0xbc, 0x41, 0xa3, 0x50, 0x5f, 0x01, 0x27, 0x56,
  0xb4, 0xbe, 0x27, 0x75, 0x06, 0xaf, 0x12, 0x2e, 0x75, 0x98, 0x8d, 0xfc,
  0x02, 0x31, 0x00, 0x8b, 0xf5, 0x77, 0x6c, 0xd4, 0xc8, 0x65, 0xaa, 0xe0,
  0x0b, 0x2c, 0xee, 0x14, 0x9d, 0x27, 0x37, 0xa4, 0xf9, 0x53, 0xa5, 0x51,
  0xe4, 0x29, 0x83, 0xd7, 0xf8, 0x90, 0x31, 0x5b, 0x42, 0x9f, 0x0a, 0xf5,
  0xfe, 0xae, 0x00, 0x68, 0xe7, 0x8c, 0x49, 0x0f, 0xb6, 0x6f, 0x5b, 0x5b,
  0x15, 0xf2, 0xe7
};
unsigned int ISRG_Root_X2_der_len = 543;

Option 2:

According to this article, you may be able to specify NULL for the certificate.

A Simple TLS Client

A good starting point in getting to grips with mbedtls is to convert the simplest HTTP client program given in Chapter 2 to HTTPS. The simplicity of this program lets you see where the changes have to be made.

What might surprise you is how easy the conversion to HTTPS is. All you have to do to the main program is add:

#include "lwip/altcp_tls.h" and replace the line which constructs the standard TCP PCB:

struct altcp_pcb *pcb = altcp_new(NULL); by:

struct altcp_tls_config *tls_config = altcp_tls_create_config_client(NULL, 0);

struct altcp_pcb *pcb = altcp_tls_new(tls_config, IPADDR_TYPE_ANY);

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.