Skip to content

Commit bb96b73

Browse files
Krzysztof Stachowiakk-stachowiak
Krzysztof Stachowiak
authored andcommitted
Add a copy of tls-client application
1 parent 98c0a54 commit bb96b73

File tree

8 files changed

+902
-0
lines changed

8 files changed

+902
-0
lines changed

tests/tls-client-psa.log

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Starting mbed-os-example-tls/tls-client
2+
Using Mbed OS
3+
Successfully connected to os.mbed.com at port 443
4+
Starting the TLS handshake...
5+
Successfully completed the TLS handshake
6+
Server certificate:
7+
Certificate verification passed
8+
Established TLS connection to os.mbed.com
9+
HTTP: Received [0-9]+ chars from server
10+
HTTP: Received '200 OK' status ... OK
11+
HTTP: Received message:
12+
Hello world!
13+
DONE

tls-client-psa/HelloHttpsClient.cpp

Lines changed: 384 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,384 @@
1+
/*
2+
* Hello world example of a TLS client: fetch an HTTPS page
3+
*
4+
* Copyright (C) 2006-2018, Arm Limited, All Rights Reserved
5+
* SPDX-License-Identifier: Apache-2.0
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
8+
* not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*
19+
* This file is part of Mbed TLS (https://tls.mbed.org)
20+
*/
21+
22+
#include "HelloHttpsClient.h"
23+
24+
#include "mbedtls/platform.h"
25+
#include "mbedtls/config.h"
26+
#include "mbedtls/ssl.h"
27+
#include "mbedtls/entropy.h"
28+
#include "mbedtls/ctr_drbg.h"
29+
#include "mbedtls/error.h"
30+
#include "mbedtls/debug.h"
31+
#include "mbedtls/x509.h"
32+
33+
#include <stdint.h>
34+
#include <string.h>
35+
#include "mbed.h"
36+
37+
const char *HelloHttpsClient::DRBG_PERSONALIZED_STR =
38+
"Mbed TLS helloword client";
39+
40+
const size_t HelloHttpsClient::ERROR_LOG_BUFFER_LENGTH = 128;
41+
42+
const char *HelloHttpsClient::TLS_PEM_CA =
43+
"-----BEGIN CERTIFICATE-----\n"
44+
"MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\n"
45+
"A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\n"
46+
"b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\n"
47+
"MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\n"
48+
"YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\n"
49+
"aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\n"
50+
"jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\n"
51+
"xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\n"
52+
"1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\n"
53+
"snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\n"
54+
"U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\n"
55+
"9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\n"
56+
"BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\n"
57+
"AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\n"
58+
"yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\n"
59+
"38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\n"
60+
"AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\n"
61+
"DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\n"
62+
"HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\n"
63+
"-----END CERTIFICATE-----\n";
64+
65+
const char *HelloHttpsClient::HTTP_REQUEST_FILE_PATH =
66+
"/media/uploads/mbed_official/hello.txt";
67+
68+
const char *HelloHttpsClient::HTTP_HELLO_STR = "Hello world!";
69+
70+
const char *HelloHttpsClient::HTTP_OK_STR = "200 OK";
71+
72+
HelloHttpsClient::HelloHttpsClient(const char *in_server_name,
73+
const char *in_server_addr,
74+
const uint16_t in_server_port) :
75+
socket(),
76+
server_name(in_server_name),
77+
server_addr(in_server_addr),
78+
server_port(in_server_port)
79+
{
80+
mbedtls_entropy_init(&entropy);
81+
mbedtls_ctr_drbg_init(&ctr_drbg);
82+
mbedtls_x509_crt_init(&cacert);
83+
mbedtls_ssl_init(&ssl);
84+
mbedtls_ssl_config_init(&ssl_conf);
85+
}
86+
87+
HelloHttpsClient::~HelloHttpsClient()
88+
{
89+
mbedtls_entropy_free(&entropy);
90+
mbedtls_ctr_drbg_free(&ctr_drbg);
91+
mbedtls_x509_crt_free(&cacert);
92+
mbedtls_ssl_free(&ssl);
93+
mbedtls_ssl_config_free(&ssl_conf);
94+
95+
socket.close();
96+
}
97+
98+
int HelloHttpsClient::run()
99+
{
100+
int ret;
101+
size_t req_len, req_offset, resp_offset;
102+
uint32_t flags;
103+
bool resp_200, resp_hello;
104+
105+
/* Configure the TCPSocket */
106+
if ((ret = configureTCPSocket()) != 0)
107+
return ret;
108+
109+
/* Configure already initialized Mbed TLS structures */
110+
if ((ret = configureTlsContexts()) != 0)
111+
return ret;
112+
113+
/* Start a connection to the server */
114+
if ((ret = socket.connect(server_addr, server_port)) != NSAPI_ERROR_OK) {
115+
mbedtls_printf("socket.connect() returned %d\n", ret);
116+
return ret;
117+
}
118+
mbedtls_printf("Successfully connected to %s at port %u\n",
119+
server_addr, server_port);
120+
121+
/* Start the TLS handshake */
122+
mbedtls_printf("Starting the TLS handshake...\n");
123+
do {
124+
ret = mbedtls_ssl_handshake(&ssl);
125+
} while(ret != 0 &&
126+
(ret == MBEDTLS_ERR_SSL_WANT_READ ||
127+
ret == MBEDTLS_ERR_SSL_WANT_WRITE));
128+
if (ret < 0) {
129+
mbedtls_printf("mbedtls_ssl_handshake() returned -0x%04X\n", -ret);
130+
return ret;
131+
}
132+
mbedtls_printf("Successfully completed the TLS handshake\n");
133+
134+
/* Fill the request buffer */
135+
ret = snprintf(gp_buf, sizeof(gp_buf),
136+
"GET %s HTTP/1.1\nHost: %s\n\n", HTTP_REQUEST_FILE_PATH,
137+
server_name);
138+
req_len = static_cast<size_t>(ret);
139+
if (ret < 0 || req_len >= sizeof(gp_buf)) {
140+
mbedtls_printf("Failed to compose HTTP request using snprintf: %d\n",
141+
ret);
142+
return ret;
143+
}
144+
145+
/* Send the HTTP request to the server over TLS */
146+
req_offset = 0;
147+
do {
148+
ret = mbedtls_ssl_write(&ssl,
149+
reinterpret_cast<const unsigned char *>(gp_buf + req_offset),
150+
req_len - req_offset);
151+
if (ret > 0)
152+
req_offset += static_cast<size_t>(ret);
153+
}
154+
while(req_offset < req_len &&
155+
(ret > 0 ||
156+
ret == MBEDTLS_ERR_SSL_WANT_WRITE ||
157+
ret == MBEDTLS_ERR_SSL_WANT_READ));
158+
if (ret < 0) {
159+
mbedtls_printf("mbedtls_ssl_write() returned -0x%04X\n", -ret);
160+
return ret;
161+
}
162+
163+
/* Print information about the TLS connection */
164+
ret = mbedtls_x509_crt_info(gp_buf, sizeof(gp_buf),
165+
"\r ", mbedtls_ssl_get_peer_cert(&ssl));
166+
if (ret < 0) {
167+
mbedtls_printf("mbedtls_x509_crt_info() returned -0x%04X\n", -ret);
168+
return ret;
169+
}
170+
mbedtls_printf("Server certificate:\n%s\n", gp_buf);
171+
172+
/* Ensure certificate verification was successful */
173+
flags = mbedtls_ssl_get_verify_result(&ssl);
174+
if (flags != 0) {
175+
ret = mbedtls_x509_crt_verify_info(gp_buf, sizeof(gp_buf),
176+
"\r ! ", flags);
177+
if (ret < 0) {
178+
mbedtls_printf("mbedtls_x509_crt_verify_info() returned "
179+
"-0x%04X\n", -ret);
180+
return ret;
181+
} else {
182+
mbedtls_printf("Certificate verification failed (flags %lu):"
183+
"\n%s\n", flags, gp_buf);
184+
return -1;
185+
}
186+
} else {
187+
mbedtls_printf("Certificate verification passed\n");
188+
}
189+
190+
mbedtls_printf("Established TLS connection to %s\n", server_name);
191+
192+
/* Read response from the server */
193+
resp_offset = 0;
194+
resp_200 = false;
195+
resp_hello = false;
196+
do {
197+
ret = mbedtls_ssl_read(&ssl,
198+
reinterpret_cast<unsigned char *>(gp_buf + resp_offset),
199+
sizeof(gp_buf) - resp_offset - 1);
200+
if (ret > 0)
201+
resp_offset += static_cast<size_t>(ret);
202+
203+
/* Ensure that the response string is null-terminated */
204+
gp_buf[resp_offset] = '\0';
205+
206+
/* Check if we received expected string */
207+
resp_200 = resp_200 || strstr(gp_buf, HTTP_OK_STR) != NULL;
208+
resp_hello = resp_hello || strstr(gp_buf, HTTP_HELLO_STR) != NULL;
209+
} while((!resp_200 || !resp_hello) &&
210+
(ret > 0 ||
211+
ret == MBEDTLS_ERR_SSL_WANT_READ || MBEDTLS_ERR_SSL_WANT_WRITE));
212+
if (ret < 0) {
213+
mbedtls_printf("mbedtls_ssl_read() returned -0x%04X\n", -ret);
214+
return ret;
215+
}
216+
217+
/* Display response information */
218+
mbedtls_printf("HTTP: Received %u chars from server\n", resp_offset);
219+
mbedtls_printf("HTTP: Received '%s' status ... %s\n", HTTP_OK_STR,
220+
resp_200 ? "OK" : "FAIL");
221+
mbedtls_printf("HTTP: Received message:\n%s\n", gp_buf);
222+
223+
return 0;
224+
}
225+
226+
int HelloHttpsClient::configureTCPSocket()
227+
{
228+
int ret;
229+
230+
NetworkInterface *network = NetworkInterface::get_default_instance();
231+
if(network == NULL) {
232+
mbedtls_printf("ERROR: No network interface found!\n");
233+
return -1;
234+
}
235+
ret = network->connect();
236+
if (ret != 0) {
237+
mbedtls_printf("Error! network->connect() returned: %d\n", ret);
238+
return ret;
239+
}
240+
241+
if ((ret = socket.open(network)) != NSAPI_ERROR_OK) {
242+
mbedtls_printf("socket.open() returned %d\n", ret);
243+
return ret;
244+
}
245+
246+
socket.set_blocking(false);
247+
248+
return 0;
249+
}
250+
251+
int HelloHttpsClient::configureTlsContexts()
252+
{
253+
int ret;
254+
255+
ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
256+
reinterpret_cast<const unsigned char *>(DRBG_PERSONALIZED_STR),
257+
strlen(DRBG_PERSONALIZED_STR) + 1);
258+
if (ret != 0) {
259+
mbedtls_printf("mbedtls_ctr_drbg_seed() returned -0x%04X\n", -ret);
260+
return ret;
261+
}
262+
263+
ret = mbedtls_x509_crt_parse(&cacert,
264+
reinterpret_cast<const unsigned char *>(TLS_PEM_CA),
265+
strlen(TLS_PEM_CA) + 1);
266+
if (ret != 0) {
267+
mbedtls_printf("mbedtls_x509_crt_parse() returned -0x%04X\n", -ret);
268+
return ret;
269+
}
270+
271+
ret = mbedtls_ssl_config_defaults(&ssl_conf, MBEDTLS_SSL_IS_CLIENT,
272+
MBEDTLS_SSL_TRANSPORT_STREAM,
273+
MBEDTLS_SSL_PRESET_DEFAULT);
274+
if (ret != 0) {
275+
mbedtls_printf("mbedtls_ssl_config_defaults() returned -0x%04X\n",
276+
-ret);
277+
return ret;
278+
}
279+
280+
mbedtls_ssl_conf_ca_chain(&ssl_conf, &cacert, NULL);
281+
mbedtls_ssl_conf_rng(&ssl_conf, mbedtls_ctr_drbg_random, &ctr_drbg);
282+
283+
/*
284+
* It is possible to disable authentication by passing
285+
* MBEDTLS_SSL_VERIFY_NONE in the call to mbedtls_ssl_conf_authmode()
286+
*/
287+
mbedtls_ssl_conf_authmode(&ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
288+
289+
/* Configure certificate verification function to clear time/date flags */
290+
mbedtls_ssl_conf_verify(&ssl_conf, sslVerify, this);
291+
292+
#if HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0
293+
mbedtls_ssl_conf_dbg(&ssl_conf, sslDebug, NULL);
294+
mbedtls_debug_set_threshold(HELLO_HTTPS_CLIENT_DEBUG_LEVEL);
295+
#endif /* HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0 */
296+
297+
if ((ret = mbedtls_ssl_setup( &ssl, &ssl_conf)) != 0) {
298+
mbedtls_printf("mbedtls_ssl_setup() returned -0x%04X\n", -ret);
299+
return ret;
300+
}
301+
302+
if ((ret = mbedtls_ssl_set_hostname( &ssl, server_name )) != 0) {
303+
mbedtls_printf("mbedtls_ssl_set_hostname() returned -0x%04X\n",
304+
-ret);
305+
return ret;
306+
}
307+
308+
mbedtls_ssl_set_bio(&ssl, static_cast<void *>(&socket), sslSend, sslRecv,
309+
NULL);
310+
311+
return 0;
312+
}
313+
314+
int HelloHttpsClient::sslRecv(void *ctx, unsigned char *buf, size_t len)
315+
{
316+
TCPSocket *socket = static_cast<TCPSocket *>(ctx);
317+
int ret = socket->recv(buf, len);
318+
319+
if (ret == NSAPI_ERROR_WOULD_BLOCK)
320+
ret = MBEDTLS_ERR_SSL_WANT_READ;
321+
else if (ret < 0)
322+
mbedtls_printf("socket.recv() returned %d\n", ret);
323+
324+
return ret;
325+
}
326+
327+
int HelloHttpsClient::sslSend(void *ctx, const unsigned char *buf, size_t len)
328+
{
329+
TCPSocket *socket = static_cast<TCPSocket *>(ctx);
330+
int ret = socket->send(buf, len);
331+
332+
if (ret == NSAPI_ERROR_WOULD_BLOCK)
333+
ret = MBEDTLS_ERR_SSL_WANT_WRITE;
334+
else if (ret < 0)
335+
mbedtls_printf("socket.send() returned %d\n", ret);
336+
337+
return ret;
338+
}
339+
340+
void HelloHttpsClient::sslDebug(void *ctx, int level, const char *file,
341+
int line, const char *str)
342+
{
343+
(void)ctx;
344+
345+
const char *p, *basename;
346+
347+
/* Extract basename from file */
348+
for (p = basename = file; *p != '\0'; p++) {
349+
if (*p == '/' || *p == '\\')
350+
basename = p + 1;
351+
}
352+
353+
mbedtls_printf("%s:%d: |%d| %s\r", basename, line, level, str);
354+
}
355+
356+
int HelloHttpsClient::sslVerify(void *ctx, mbedtls_x509_crt *crt, int depth,
357+
uint32_t *flags)
358+
{
359+
int ret = 0;
360+
361+
/*
362+
* If MBEDTLS_HAVE_TIME_DATE is defined, then the certificate date and time
363+
* validity checks will probably fail because this application does not set
364+
* up the clock correctly. We filter out date and time related failures
365+
* instead
366+
*/
367+
*flags &= ~MBEDTLS_X509_BADCERT_FUTURE & ~MBEDTLS_X509_BADCERT_EXPIRED;
368+
369+
#if HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0
370+
HelloHttpsClient *client = static_cast<HelloHttpsClient *>(ctx);
371+
372+
ret = mbedtls_x509_crt_info(client->gp_buf, sizeof(gp_buf), "\r ", crt);
373+
if (ret < 0) {
374+
mbedtls_printf("mbedtls_x509_crt_info() returned -0x%04X\n", -ret);
375+
} else {
376+
ret = 0;
377+
mbedtls_printf("Verifying certificate at depth %d:\n%s\n",
378+
depth, client->gp_buf);
379+
}
380+
#endif /* HELLO_HTTPS_CLIENT_DEBUG_LEVEL > 0 */
381+
382+
return ret;
383+
}
384+

0 commit comments

Comments
 (0)