#include "board.h" #include /* wolfssl includes. */ #include #include #include "api.h" #include "sockets.h" #define HTTPS_GET_API "GET / HTTP/1.1\r\n" /* HOST, host-port, URI */\ "Host: www.baidu.com\r\n" /* server name */ \ "\r\n" typedef struct { uint32_t ContentLength; }https_header_t; const char s__host_name[] = "www.baidu.com"; static const unsigned char __ssl_root_certificate[] = "-----BEGIN CERTIFICATE-----" "MIIJ7DCCCNSgAwIBAgIMTkADpl62gfh/S9jrMA0GCSqGSIb3DQEBCwUAMFAxCzAJ" "BgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSYwJAYDVQQDEx1H" "bG9iYWxTaWduIFJTQSBPViBTU0wgQ0EgMjAxODAeFw0yNDA3MDgwMTQxMDJaFw0y" "NTA4MDkwMTQxMDFaMIGAMQswCQYDVQQGEwJDTjEQMA4GA1UECBMHYmVpamluZzEQ" "MA4GA1UEBxMHYmVpamluZzE5MDcGA1UEChMwQmVpamluZyBCYWlkdSBOZXRjb20g" "U2NpZW5jZSBUZWNobm9sb2d5IENvLiwgTHRkMRIwEAYDVQQDEwliYWlkdS5jb20w" "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1wFMskJ2dseOqoHptNwot" "FOhdBERsZ4VQnRNKXEEXMQEfgbNtScQ+C/Z+IpRAt1EObhYlifn74kt2nTsCQLng" "jfQkRVBuO/6PNGKdlCYGBeGqAL7xR+LOyHnpH9mwCBJc+WVt2zYM9I1clpXCJa+I" "tsq6qpb1AGoQxRDZ2n4K8Gd61wgNCPHDHc/Lk9NPJoUBMvYWvEe5lKhHsJtWtHe4" "QC3y58Vi+r5R0PWn2hyTBr9fCo58p/stDiRqp9Irtmi95YhwkNkmgwpMB8RhcGoN" "h+Uw5TkPZVj4AVaoPT1ED/GMKZev0+ypmp0+nmjVg2x7yUfLUfp3X7oBdI4TS2hv" "AgMBAAGjggaTMIIGjzAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0TAQH/BAIwADCBjgYI" "KwYBBQUHAQEEgYEwfzBEBggrBgEFBQcwAoY4aHR0cDovL3NlY3VyZS5nbG9iYWxz" "aWduLmNvbS9jYWNlcnQvZ3Nyc2FvdnNzbGNhMjAxOC5jcnQwNwYIKwYBBQUHMAGG" "K2h0dHA6Ly9vY3NwLmdsb2JhbHNpZ24uY29tL2dzcnNhb3Zzc2xjYTIwMTgwVgYD" "VR0gBE8wTTBBBgkrBgEEAaAyARQwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cu" "Z2xvYmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wCAYGZ4EMAQICMD8GA1UdHwQ4MDYw" "NKAyoDCGLmh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vZ3Nyc2FvdnNzbGNhMjAx" "OC5jcmwwggNhBgNVHREEggNYMIIDVIIJYmFpZHUuY29tggxiYWlmdWJhby5jb22C" "DHd3dy5iYWlkdS5jboIQd3d3LmJhaWR1LmNvbS5jboIPbWN0LnkubnVvbWkuY29t" "ggthcG9sbG8uYXV0b4IGZHd6LmNuggsqLmJhaWR1LmNvbYIOKi5iYWlmdWJhby5j" "b22CESouYmFpZHVzdGF0aWMuY29tgg4qLmJkc3RhdGljLmNvbYILKi5iZGltZy5j" "b22CDCouaGFvMTIzLmNvbYILKi5udW9taS5jb22CDSouY2h1YW5rZS5jb22CDSou" "dHJ1c3Rnby5jb22CDyouYmNlLmJhaWR1LmNvbYIQKi5leXVuLmJhaWR1LmNvbYIP" "Ki5tYXAuYmFpZHUuY29tgg8qLm1iZC5iYWlkdS5jb22CESouZmFueWkuYmFpZHUu" "Y29tgg4qLmJhaWR1YmNlLmNvbYIMKi5taXBjZG4uY29tghAqLm5ld3MuYmFpZHUu" "Y29tgg4qLmJhaWR1cGNzLmNvbYIMKi5haXBhZ2UuY29tggsqLmFpcGFnZS5jboIN" "Ki5iY2Vob3N0LmNvbYIQKi5zYWZlLmJhaWR1LmNvbYIOKi5pbS5iYWlkdS5jb22C" "EiouYmFpZHVjb250ZW50LmNvbYILKi5kbG5lbC5jb22CCyouZGxuZWwub3JnghIq" "LmR1ZXJvcy5iYWlkdS5jb22CDiouc3UuYmFpZHUuY29tgggqLjkxLmNvbYISKi5o" "YW8xMjMuYmFpZHUuY29tgg0qLmFwb2xsby5hdXRvghIqLnh1ZXNodS5iYWlkdS5j" "b22CESouYmouYmFpZHViY2UuY29tghEqLmd6LmJhaWR1YmNlLmNvbYIOKi5zbWFy" "dGFwcHMuY26CDSouYmR0anJjdi5jb22CDCouaGFvMjIyLmNvbYIMKi5oYW9rYW4u" "Y29tgg8qLnBhZS5iYWlkdS5jb22CESoudmQuYmRzdGF0aWMuY29tghEqLmNsb3Vk" "LmJhaWR1LmNvbYISY2xpY2suaG0uYmFpZHUuY29tghBsb2cuaG0uYmFpZHUuY29t" "ghBjbS5wb3MuYmFpZHUuY29tghB3bi5wb3MuYmFpZHUuY29tghR1cGRhdGUucGFu" "LmJhaWR1LmNvbTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHwYDVR0j" "BBgwFoAU+O9/8s14Z6jeb48kjYjxhwMCs+swHQYDVR0OBBYEFK3KAFTK2OWUto+D" "2ieAKE5ZJDsYMIIBfwYKKwYBBAHWeQIEAgSCAW8EggFrAWkAdgCvGBoo1oyj4KmK" "TJxnqwn4u7wiuq68sTijoZ3T+bYDDQAAAZCQAGzzAAAEAwBHMEUCIFwF5Jc+zyIF" "Gnpxchz9fY1qzlqg/oVrs2nnuxcpBuuIAiEAu3scD6u51VOP/9aMSqR2yKHZLbHw" "Fos9U7AzSdLIZa8AdgAS8U40vVNyTIQGGcOPP3oT+Oe1YoeInG0wBYTr5YYmOgAA" "AZCQAG3iAAAEAwBHMEUCIBBYQ6NP7VUDgfktWRg5QxT23QAbTqYovtV2D9O8Qc0T" "AiEA2P7+44EvQ5adwL1y56oyxv/m+Gujeia7wpo7+Xbhv6MAdwAN4fIwK9MNwUBi" "EgnqVS78R3R8sdfpMO8OQh60fk6qNAAAAZCQAGy+AAAEAwBIMEYCIQDU7Hxtx4c9" "p9Jd+cr+DCMtyRYSc0b8cktCcbMmtDE9ygIhAIpJd4yb7jtxnaEC8oLWDushbK1v" "0BIuZu6YrQvsf1nQMA0GCSqGSIb3DQEBCwUAA4IBAQCh9DfewC012/+fHZpmSpCn" "y+h3/+ClAZ8cJVO+LCmYz9r6bkyhcFquJ5qUpyoW8AYtU0oUFlqH6zLIyujW+7lq" "wFxB6NsXKKdwBKmMbmnZr2Fca5f+TtwD/GDJgG/egr7fI1u8194j9KEl8cK8Fujm" "+UsoWklEzd1It9xkLazJR/6SwbhSR4k610pvj8rQrS4wAewuYFDaDOfqsHtDIsx1" "tZfIfoB/O1wGWZQJU2M9wC8uYq0jQ2Q0MQJXuyJz04MFiGrPAS1Uk8mWd8M+3p65" "Xy4iAf8uWzs1M+fcwBE8BNBghkQgE+FSUsldm+5ZBCazU0joJswzldWisXMLTagI" "-----END CERTIFICATE-----" ; static const size_t __ssl_root_certificate_len = sizeof(__ssl_root_certificate); /* *行长度不包含行尾的\r\n */ static int https_content_get_line_len(const char *https_content, int content_len) { int ret = -1; int step = 0; int cnt; if (!https_content || (content_len <= 0)) goto exit; for (cnt = 0; cnt < content_len; cnt++) { if (https_content[cnt] == '\r') { step = 1; } else if (https_content[cnt] == '\n') { if (step == 1) { ret = cnt - 1; break; } } else { step = 0; } } exit: return ret; } static int https_content_get_line_pos(const char *https_content, int content_len, uint32_t line) { int pos = -1; int cur_pos; int step = 0; int line_cnt = 0; if (!https_content || (content_len <= 0)) goto exit; for (cur_pos = 0; cur_pos < content_len; cur_pos++) { if (step == 2) { line_cnt++; step = 0; if (line_cnt == line) { pos = cur_pos; break; } } if (https_content[cur_pos] == '\r') { step = 1; } else if (https_content[cur_pos] == '\n') { if (step == 1) { step = 2; } } else { step = 0; } } exit: return pos; } static int https_get_content_length(const char *https_content, int content_len) { int ret = -1; int line_len = 0; int pos = 0; int pos_cnt = 0; const char header_start[] = "HTTP"; const char ContentLength[] = "Content-Length"; if (!https_content || content_len < 4) { ret = -1; goto exit; } if (memcmp((const void *)https_content, (const void *)header_start, 4) != 0) { ret = -1; goto exit; } while (1) { pos = https_content_get_line_pos(&https_content[pos_cnt], content_len - pos_cnt, 1); if (pos > -1) { pos_cnt += pos; line_len = https_content_get_line_len(&https_content[pos_cnt], content_len - pos_cnt); if (line_len <= 0) { break; } else if (line_len >= strlen(ContentLength)) { if (memcmp((const char *)&https_content[pos_cnt], (const char *)ContentLength, strlen(ContentLength)) == 0) { sscanf((const char *)&https_content[pos_cnt + strlen(ContentLength) + 2], "%d\r\n", &ret); break; } } } else { break; } } exit: return ret; } static int https_get_content_pos(const char *https_content, int content_len) { int ret = -1; int line_len = 0; int pos = 0; int pos_cnt = 0; int flag = 0; const char header_start[] = "HTTP"; if (!https_content || content_len < 4) { ret = -1; goto exit; } if (memcmp((const void *)https_content, (const void *)header_start, 4) != 0) { ret = -1; goto exit; } while (1) { pos = https_content_get_line_pos(&https_content[pos_cnt], content_len - pos_cnt, 1); if (pos > -1) { pos_cnt += pos; line_len = https_content_get_line_len(&https_content[pos_cnt], content_len - pos_cnt); if (flag) { ret = pos_cnt; break; } else { if (line_len < 0) { break; } else if (line_len == 0) { flag = 1; } } } else { break; } } exit: return ret; } void https_client_test(void) { WOLFSSL_CTX* ctx = NULL; ip_addr_t server_ip ; err_t err = ERR_OK; int sockfd; struct sockaddr_in servaddr; WOLFSSL* ssl = NULL; char http_head[] = HTTPS_GET_API; int recv_len = 0; int total_recv_len = 0; char *rbuf = NULL; uint32_t pg_size = 1024 * 16; int ContentLength = -1; int content_start_pos = -1; //创建 wolfssl 需要的空间等配置 if ( WOLFSSL_SUCCESS != wolfSSL_Init()) { printf("-------------- wolfssl init fail! --------------\n"); goto exit; } //初始化 结构体 WOLFSSL_CTX if ((ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())) == NULL) { printf("-------------- wolfSSL_CTX_new fail! --------------\n"); goto exit; } //加载 CA 证书到 WOLFSSL_CTX if ( wolfSSL_CTX_load_verify_buffer(ctx, (unsigned char *)__ssl_root_certificate, \ __ssl_root_certificate_len, WOLFSSL_FILETYPE_PEM) != SSL_SUCCESS) { printf("-------------- wolfSSL_CTX_load_verify_buffer fail! --------------\n"); goto exit; } //进行域名解析 err = netconn_gethostbyname(s__host_name, &server_ip); if (err != ERR_OK) { printf("-------------- netconn_gethostbyname fail! --------------\n"); goto exit; } if (server_ip.addr == 0) { printf("-------------- DNS fail! --------------\n"); goto exit; } // 进行 socket 连接 sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) goto exit; memset(&servaddr, sizeof(servaddr), 0); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(443); inet_pton(AF_INET, inet_ntoa(server_ip), &servaddr.sin_addr); /* Connect to socket file descriptor */ if (0 > connect(sockfd, (struct sockaddr*) &servaddr, sizeof(servaddr))) { printf("-------------- https connect socket fail! --------------\n"); goto exit; } //进行 SSL 的初始化 wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); // 尝试解决 -188, -155 if ((ssl = wolfSSL_new(ctx)) == NULL) { printf("-------------- wolfSSL_new fail! --------------\n"); goto exit; } //进行 SSL 和 socket 绑定 if( WOLFSSL_SUCCESS != wolfSSL_set_fd(ssl, sockfd)) { printf("-------------- wolfSSL_set_fd fail! --------------\n"); goto exit; } //访问 if (wolfSSL_write(ssl, http_head, strlen(http_head)) != strlen(http_head)) { printf("-------------- wolfSSL_write fail! --------------\n"); goto exit; } //接收 for(;;) { if (total_recv_len == 0) rbuf = (char *)pvPortRealloc(rbuf, pg_size); else rbuf = (char *)pvPortRealloc(rbuf, total_recv_len + pg_size); if (!rbuf) { printf("realloc fail!\n"); goto exit; } if ((ContentLength > 0) && (content_start_pos > 0)) { if (((ContentLength + content_start_pos) - total_recv_len) >= pg_size) { recv_len = wolfSSL_read(ssl, rbuf + total_recv_len, pg_size); } else { recv_len = wolfSSL_read(ssl, rbuf + total_recv_len, ((ContentLength + content_start_pos) - total_recv_len)); } } else { recv_len = wolfSSL_read(ssl, rbuf + total_recv_len, pg_size); } if(recv_len <= 0) { break; } total_recv_len += recv_len; if ((ContentLength > 0) && (content_start_pos > 0)) { if ((ContentLength + content_start_pos) <= total_recv_len) break; } if (ContentLength == -1) { ContentLength = https_get_content_length((const char *)rbuf, total_recv_len); if (ContentLength > 0) printf("ContentLength = %d\n", ContentLength); } if ((ContentLength > 0) && (content_start_pos == -1)) { content_start_pos = https_get_content_pos((const char *)rbuf, total_recv_len); if (content_start_pos > 0) printf("content_start_pos = %d\n", content_start_pos); } } printf("\n ========== \n\n"); printf("https recv data : recv_len = 0x%x\n",total_recv_len); printf("addr:0x%x\n", (uint32_t)rbuf); printf("\n ========== \n\n"); exit: //释放空间 if (ssl) wolfSSL_free(ssl); /* Free WOLFSSL object */ if (ctx) wolfSSL_CTX_free(ctx); /* Free WOLFSSL_CTX object */ wolfSSL_Cleanup(); /* Free wolfSSL */ //关闭 socket if (sockfd != -1) closesocket(sockfd); if (rbuf) vPortFree((void *)rbuf); return; }