Changes to enabled on-line compiler

Committer:
JMF
Date:
Wed May 30 20:59:51 2018 +0000
Revision:
0:082731ede69f
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JMF 0:082731ede69f 1 /*
JMF 0:082731ede69f 2 * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
JMF 0:082731ede69f 3 *
JMF 0:082731ede69f 4 * Licensed under the Apache License, Version 2.0 (the "License").
JMF 0:082731ede69f 5 * You may not use this file except in compliance with the License.
JMF 0:082731ede69f 6 * A copy of the License is located at
JMF 0:082731ede69f 7 *
JMF 0:082731ede69f 8 * http://aws.amazon.com/apache2.0
JMF 0:082731ede69f 9 *
JMF 0:082731ede69f 10 * or in the "license" file accompanying this file. This file is distributed
JMF 0:082731ede69f 11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
JMF 0:082731ede69f 12 * express or implied. See the License for the specific language governing
JMF 0:082731ede69f 13 * permissions and limitations under the License.
JMF 0:082731ede69f 14 */
JMF 0:082731ede69f 15
JMF 0:082731ede69f 16 #include "mbed.h"
JMF 0:082731ede69f 17
JMF 0:082731ede69f 18 #include "easy-connect.h"
JMF 0:082731ede69f 19
JMF 0:082731ede69f 20 #define MBEDTLS_FS_IO 1
JMF 0:082731ede69f 21
JMF 0:082731ede69f 22 #include <stdbool.h>
JMF 0:082731ede69f 23 #include <string.h>
JMF 0:082731ede69f 24 #include <timer_platform.h>
JMF 0:082731ede69f 25 #include <network_interface.h>
JMF 0:082731ede69f 26
JMF 0:082731ede69f 27 #include "mbedtls/platform.h"
JMF 0:082731ede69f 28 #include "mbedtls/ssl.h"
JMF 0:082731ede69f 29 #include "mbedtls/entropy.h"
JMF 0:082731ede69f 30 #include "mbedtls/ctr_drbg.h"
JMF 0:082731ede69f 31 #include "mbedtls/error.h"
JMF 0:082731ede69f 32 #include "mbedtls/x509_crt.h"
JMF 0:082731ede69f 33 #include "mbedtls/pk.h"
JMF 0:082731ede69f 34
JMF 0:082731ede69f 35 #if DEBUG_LEVEL > 0
JMF 0:082731ede69f 36 #include "mbedtls/debug.h"
JMF 0:082731ede69f 37 #endif
JMF 0:082731ede69f 38
JMF 0:082731ede69f 39 #include "aws_iot_error.h"
JMF 0:082731ede69f 40 #include "aws_iot_log.h"
JMF 0:082731ede69f 41 #include "network_interface.h"
JMF 0:082731ede69f 42 #include "network_platform.h"
JMF 0:082731ede69f 43
JMF 0:082731ede69f 44 #include "awscerts.h"
JMF 0:082731ede69f 45
JMF 0:082731ede69f 46 /* This is the value used for ssl read timeout (in msec) */
JMF 0:082731ede69f 47 #define IOT_SSL_READ_TIMEOUT 10000
JMF 0:082731ede69f 48
JMF 0:082731ede69f 49 /* This defines the value of the debug buffer that gets allocated.
JMF 0:082731ede69f 50 * The value can be altered based on memory constraints
JMF 0:082731ede69f 51 */
JMF 0:082731ede69f 52 #ifdef ENABLE_IOT_DEBUG
JMF 0:082731ede69f 53 #define MBEDTLS_DEBUG_BUFFER_SIZE 2048
JMF 0:082731ede69f 54 #endif
JMF 0:082731ede69f 55
JMF 0:082731ede69f 56
JMF 0:082731ede69f 57 void mbedtls_aws_init( mbedtls_net_context * );
JMF 0:082731ede69f 58 int mbedtls_aws_connect( mbedtls_net_context *, const char *host, uint16_t port, int proto );
JMF 0:082731ede69f 59 int mbedtls_aws_bind( mbedtls_net_context *, const char *bind_ip, const char *port, int proto );
JMF 0:082731ede69f 60 int mbedtls_aws_accept( mbedtls_net_context *bind_ctx, mbedtls_net_context *client_ctx, void *client_ip, size_t buf_size, size_t *ip_len ) ;
JMF 0:082731ede69f 61 void mbedtls_aws_usleep( unsigned long );
JMF 0:082731ede69f 62 int mbedtls_aws_recv( void *, unsigned char *, size_t );
JMF 0:082731ede69f 63 int mbedtls_aws_recv_timeout( void *, unsigned char *, size_t , uint32_t );
JMF 0:082731ede69f 64 int mbedtls_aws_send( void *, const unsigned char *, size_t );
JMF 0:082731ede69f 65 void mbedtls_aws_free( mbedtls_net_context * );
JMF 0:082731ede69f 66
JMF 0:082731ede69f 67 /*
JMF 0:082731ede69f 68 * This is a function to do further verification if needed on the cert received
JMF 0:082731ede69f 69 */
JMF 0:082731ede69f 70
JMF 0:082731ede69f 71 static int _iot_tls_verify_cert(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
JMF 0:082731ede69f 72 {
JMF 0:082731ede69f 73 char buf[1024];
JMF 0:082731ede69f 74 ((void) data);
JMF 0:082731ede69f 75 FUNC_ENTRY;
JMF 0:082731ede69f 76
JMF 0:082731ede69f 77 IOT_DEBUG("Verify requested for (Depth %d):", depth);
JMF 0:082731ede69f 78 mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
JMF 0:082731ede69f 79 IOT_DEBUG("%s", buf);
JMF 0:082731ede69f 80
JMF 0:082731ede69f 81 if((*flags) == 0) {
JMF 0:082731ede69f 82 IOT_DEBUG("This certificate has no flags");
JMF 0:082731ede69f 83 } else {
JMF 0:082731ede69f 84 IOT_DEBUG(buf, sizeof(buf), " ! ", *flags);
JMF 0:082731ede69f 85 IOT_DEBUG("%s", buf);
JMF 0:082731ede69f 86 }
JMF 0:082731ede69f 87
JMF 0:082731ede69f 88 FUNC_EXIT_RC( 0);
JMF 0:082731ede69f 89 }
JMF 0:082731ede69f 90
JMF 0:082731ede69f 91 void _iot_tls_set_connect_params(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation,
JMF 0:082731ede69f 92 char *pDevicePrivateKeyLocation, char *pDestinationURL,
JMF 0:082731ede69f 93 uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag)
JMF 0:082731ede69f 94 {
JMF 0:082731ede69f 95 FUNC_ENTRY;
JMF 0:082731ede69f 96 pNetwork->tlsConnectParams.DestinationPort = destinationPort;
JMF 0:082731ede69f 97 pNetwork->tlsConnectParams.pDestinationURL = pDestinationURL;
JMF 0:082731ede69f 98 pNetwork->tlsConnectParams.pDeviceCertLocation = pDeviceCertLocation;
JMF 0:082731ede69f 99 pNetwork->tlsConnectParams.pDevicePrivateKeyLocation = pDevicePrivateKeyLocation;
JMF 0:082731ede69f 100 pNetwork->tlsConnectParams.pRootCALocation = pRootCALocation;
JMF 0:082731ede69f 101 pNetwork->tlsConnectParams.timeout_ms = timeout_ms;
JMF 0:082731ede69f 102 pNetwork->tlsConnectParams.ServerVerificationFlag = ServerVerificationFlag;
JMF 0:082731ede69f 103 }
JMF 0:082731ede69f 104
JMF 0:082731ede69f 105 IoT_Error_t iot_tls_init(Network *pNetwork, char *pRootCALocation, char *pDeviceCertLocation,
JMF 0:082731ede69f 106 char *pDevicePrivateKeyLocation, char *pDestinationURL,
JMF 0:082731ede69f 107 uint16_t destinationPort, uint32_t timeout_ms, bool ServerVerificationFlag)
JMF 0:082731ede69f 108 {
JMF 0:082731ede69f 109 FUNC_ENTRY;
JMF 0:082731ede69f 110 _iot_tls_set_connect_params(pNetwork, pRootCALocation, pDeviceCertLocation, pDevicePrivateKeyLocation,
JMF 0:082731ede69f 111 pDestinationURL, destinationPort, timeout_ms, ServerVerificationFlag);
JMF 0:082731ede69f 112
JMF 0:082731ede69f 113 pNetwork->connect = iot_tls_connect;
JMF 0:082731ede69f 114 pNetwork->read = iot_tls_read;
JMF 0:082731ede69f 115 pNetwork->write = iot_tls_write;
JMF 0:082731ede69f 116 pNetwork->disconnect = iot_tls_disconnect;
JMF 0:082731ede69f 117 pNetwork->isConnected = iot_tls_is_connected;
JMF 0:082731ede69f 118 pNetwork->destroy = iot_tls_destroy;
JMF 0:082731ede69f 119
JMF 0:082731ede69f 120 pNetwork->tlsDataParams.flags = 0;
JMF 0:082731ede69f 121
JMF 0:082731ede69f 122 FUNC_EXIT_RC( AWS_SUCCESS);
JMF 0:082731ede69f 123 }
JMF 0:082731ede69f 124
JMF 0:082731ede69f 125 IoT_Error_t iot_tls_is_connected(Network *pNetwork)
JMF 0:082731ede69f 126 {
JMF 0:082731ede69f 127 FUNC_ENTRY;
JMF 0:082731ede69f 128 /* Use this to add implementation which can check for physical layer disconnect */
JMF 0:082731ede69f 129 FUNC_EXIT_RC( NETWORK_PHYSICAL_LAYER_CONNECTED);
JMF 0:082731ede69f 130 }
JMF 0:082731ede69f 131
JMF 0:082731ede69f 132 IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params)
JMF 0:082731ede69f 133 {
JMF 0:082731ede69f 134 int ret = 0;
JMF 0:082731ede69f 135 const char *pers = "aws_iot_tls_wrapper";
JMF 0:082731ede69f 136 TLSDataParams *tlsDataParams = NULL;
JMF 0:082731ede69f 137 char vrfy_buf[512];
JMF 0:082731ede69f 138 const char *alpnProtocols[] = { "x-amzn-mqtt-ca", NULL };
JMF 0:082731ede69f 139
JMF 0:082731ede69f 140 FUNC_ENTRY;
JMF 0:082731ede69f 141
JMF 0:082731ede69f 142 if(pNetwork == NULL) {
JMF 0:082731ede69f 143 FUNC_EXIT_RC(NULL_VALUE_ERROR);
JMF 0:082731ede69f 144 }
JMF 0:082731ede69f 145
JMF 0:082731ede69f 146 if( params != NULL) {
JMF 0:082731ede69f 147 _iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation,
JMF 0:082731ede69f 148 params->pDevicePrivateKeyLocation, params->pDestinationURL,
JMF 0:082731ede69f 149 params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag);
JMF 0:082731ede69f 150 }
JMF 0:082731ede69f 151
JMF 0:082731ede69f 152 tlsDataParams = &(pNetwork->tlsDataParams);
JMF 0:082731ede69f 153
JMF 0:082731ede69f 154
JMF 0:082731ede69f 155 mbedtls_entropy_init(&(tlsDataParams->entropy));
JMF 0:082731ede69f 156 mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg));
JMF 0:082731ede69f 157 mbedtls_x509_crt_init(&(tlsDataParams->clicert));
JMF 0:082731ede69f 158 mbedtls_x509_crt_init(&(tlsDataParams->cacert));
JMF 0:082731ede69f 159 mbedtls_ssl_init(&(tlsDataParams->ssl));
JMF 0:082731ede69f 160 mbedtls_ssl_config_init(&(tlsDataParams->conf));
JMF 0:082731ede69f 161 mbedtls_pk_init(&(tlsDataParams->pkey));
JMF 0:082731ede69f 162
JMF 0:082731ede69f 163 IOT_DEBUG("\nSeed the random number generator...");
JMF 0:082731ede69f 164 if((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy),
JMF 0:082731ede69f 165 (const unsigned char *) pers,
JMF 0:082731ede69f 166 strlen(pers))) != 0) {
JMF 0:082731ede69f 167 IOT_ERROR(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret);
JMF 0:082731ede69f 168 FUNC_EXIT_RC(NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED);
JMF 0:082731ede69f 169 }
JMF 0:082731ede69f 170
JMF 0:082731ede69f 171 IOT_DEBUG("Load the IoT certificate ...");
JMF 0:082731ede69f 172 #ifdef USING_SD_CARD
JMF 0:082731ede69f 173 ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert), pNetwork->tlsConnectParams.pDeviceCertLocation);
JMF 0:082731ede69f 174 #else
JMF 0:082731ede69f 175 ret = mbedtls_x509_crt_parse(&(tlsDataParams->clicert), (const unsigned char*)aws_iot_certificate,
JMF 0:082731ede69f 176 strlen(aws_iot_certificate)+1);
JMF 0:082731ede69f 177 #endif
JMF 0:082731ede69f 178 if(ret != 0) {
JMF 0:082731ede69f 179 IOT_ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing device cert\n\n", -ret);
JMF 0:082731ede69f 180 FUNC_EXIT_RC(NETWORK_X509_DEVICE_CRT_PARSE_ERROR);
JMF 0:082731ede69f 181 }
JMF 0:082731ede69f 182
JMF 0:082731ede69f 183 IOT_DEBUG("Load the private key ...");
JMF 0:082731ede69f 184 #ifdef USING_SD_CARD
JMF 0:082731ede69f 185 ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey), pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, "");
JMF 0:082731ede69f 186 #else
JMF 0:082731ede69f 187 ret = mbedtls_pk_parse_key(&(tlsDataParams->pkey), (const unsigned char*)aws_iot_private_key,
JMF 0:082731ede69f 188 strlen(aws_iot_private_key)+1, NULL, 0 );
JMF 0:082731ede69f 189 #endif
JMF 0:082731ede69f 190 if(ret != 0) {
JMF 0:082731ede69f 191 IOT_ERROR(" failed\n ! mbedtls_pk_parse_key returned -0x%x while parsing private key\n\n", -ret);
JMF 0:082731ede69f 192 IOT_DEBUG(" path : %s ", pNetwork->tlsConnectParams.pDevicePrivateKeyLocation);
JMF 0:082731ede69f 193 FUNC_EXIT_RC(NETWORK_PK_PRIVATE_KEY_PARSE_ERROR);
JMF 0:082731ede69f 194 }
JMF 0:082731ede69f 195
JMF 0:082731ede69f 196 IOT_DEBUG("Load the CA root certificate ...");
JMF 0:082731ede69f 197 #ifdef USING_SD_CARD
JMF 0:082731ede69f 198 ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation);
JMF 0:082731ede69f 199 #else
JMF 0:082731ede69f 200 ret = mbedtls_x509_crt_parse(&(tlsDataParams->cacert), (const unsigned char*)aws_iot_rootCA,
JMF 0:082731ede69f 201 sizeof(aws_iot_rootCA));
JMF 0:082731ede69f 202 #endif
JMF 0:082731ede69f 203 if(ret < 0) {
JMF 0:082731ede69f 204 IOT_ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing root cert\n\n", -ret);
JMF 0:082731ede69f 205 FUNC_EXIT_RC(NETWORK_X509_ROOT_CRT_PARSE_ERROR);
JMF 0:082731ede69f 206 }
JMF 0:082731ede69f 207
JMF 0:082731ede69f 208 IOT_DEBUG("done.\nSetting up the SSL/TLS structure...");
JMF 0:082731ede69f 209 if((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf),
JMF 0:082731ede69f 210 MBEDTLS_SSL_IS_CLIENT,
JMF 0:082731ede69f 211 MBEDTLS_SSL_TRANSPORT_STREAM,
JMF 0:082731ede69f 212 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
JMF 0:082731ede69f 213 IOT_ERROR(" failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret);
JMF 0:082731ede69f 214 FUNC_EXIT_RC(SSL_CONNECTION_ERROR);
JMF 0:082731ede69f 215 }
JMF 0:082731ede69f 216
JMF 0:082731ede69f 217 mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL);
JMF 0:082731ede69f 218 mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg));
JMF 0:082731ede69f 219
JMF 0:082731ede69f 220 if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) {
JMF 0:082731ede69f 221 IOT_ERROR(" failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret);
JMF 0:082731ede69f 222 FUNC_EXIT_RC(SSL_CONNECTION_ERROR);
JMF 0:082731ede69f 223 }
JMF 0:082731ede69f 224
JMF 0:082731ede69f 225 if((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) {
JMF 0:082731ede69f 226 IOT_ERROR(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
JMF 0:082731ede69f 227 FUNC_EXIT_RC(SSL_CONNECTION_ERROR);
JMF 0:082731ede69f 228 }
JMF 0:082731ede69f 229 IOT_DEBUG("Set the SSL BIO ...");
JMF 0:082731ede69f 230 mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_aws_send, NULL,
JMF 0:082731ede69f 231 mbedtls_aws_recv_timeout);
JMF 0:082731ede69f 232 mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL);
JMF 0:082731ede69f 233 if(pNetwork->tlsConnectParams.ServerVerificationFlag == true)
JMF 0:082731ede69f 234 mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED);
JMF 0:082731ede69f 235 else
JMF 0:082731ede69f 236 mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL);
JMF 0:082731ede69f 237
JMF 0:082731ede69f 238 if((ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert),
JMF 0:082731ede69f 239 &(tlsDataParams->pkey))) != 0) {
JMF 0:082731ede69f 240 IOT_ERROR(" failed\n!!! mbedtls_ssl_conf_own_cert returned %d\n\n", ret);
JMF 0:082731ede69f 241 FUNC_EXIT_RC(SSL_CONNECTION_ERROR);
JMF 0:082731ede69f 242 }
JMF 0:082731ede69f 243
JMF 0:082731ede69f 244 mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms);
JMF 0:082731ede69f 245
JMF 0:082731ede69f 246 /* Use the AWS IoT ALPN extension for MQTT if port 443 is requested. */
JMF 0:082731ede69f 247 if(443 == pNetwork->tlsConnectParams.DestinationPort) {
JMF 0:082731ede69f 248 if((ret = mbedtls_ssl_conf_alpn_protocols(&(tlsDataParams->conf), alpnProtocols)) != 0) {
JMF 0:082731ede69f 249 IOT_ERROR(" failed\n ! mbedtls_ssl_conf_alpn_protocols returned -0x%x\n\n", -ret);
JMF 0:082731ede69f 250 FUNC_EXIT_RC(SSL_CONNECTION_ERROR);
JMF 0:082731ede69f 251 }
JMF 0:082731ede69f 252 }
JMF 0:082731ede69f 253
JMF 0:082731ede69f 254 mbedtls_aws_init(&(tlsDataParams->server_fd));
JMF 0:082731ede69f 255 if( (tlsDataParams->server_fd).fd == -1 ) {
JMF 0:082731ede69f 256 IOT_ERROR(" Network connected failed!\n");
JMF 0:082731ede69f 257 FUNC_EXIT_RC(NETWORK_ERR_NET_CONNECT_FAILED);
JMF 0:082731ede69f 258 }
JMF 0:082731ede69f 259
JMF 0:082731ede69f 260 IOT_DEBUG("Connecting to %s/%d...", pNetwork->tlsConnectParams.pDestinationURL, pNetwork->tlsConnectParams.DestinationPort);
JMF 0:082731ede69f 261 if((ret = mbedtls_aws_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL,
JMF 0:082731ede69f 262 pNetwork->tlsConnectParams.DestinationPort,
JMF 0:082731ede69f 263 MBEDTLS_NET_PROTO_TCP)) != 0) {
JMF 0:082731ede69f 264 IOT_ERROR(" failed\n ! mbedtls_aws_connect returned -0x%x\n\n", -ret);
JMF 0:082731ede69f 265 switch(ret) {
JMF 0:082731ede69f 266 case MBEDTLS_ERR_NET_SOCKET_FAILED:
JMF 0:082731ede69f 267 FUNC_EXIT_RC(NETWORK_ERR_NET_SOCKET_FAILED);
JMF 0:082731ede69f 268 case MBEDTLS_ERR_NET_UNKNOWN_HOST:
JMF 0:082731ede69f 269 FUNC_EXIT_RC(NETWORK_ERR_NET_UNKNOWN_HOST);
JMF 0:082731ede69f 270 case MBEDTLS_ERR_NET_CONNECT_FAILED:
JMF 0:082731ede69f 271 default:
JMF 0:082731ede69f 272 FUNC_EXIT_RC(NETWORK_ERR_NET_CONNECT_FAILED);
JMF 0:082731ede69f 273 };
JMF 0:082731ede69f 274 }
JMF 0:082731ede69f 275
JMF 0:082731ede69f 276 IOT_DEBUG("\n\nPerform the SSL/TLS handshake...\n\n\n\n");
JMF 0:082731ede69f 277
JMF 0:082731ede69f 278 while((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) {
JMF 0:082731ede69f 279 if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
JMF 0:082731ede69f 280 IOT_ERROR(" failed\n ! mbedtls_ssl_handshake returned -0x%x (%d)\n", -ret, ret);
JMF 0:082731ede69f 281 if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
JMF 0:082731ede69f 282 IOT_ERROR( "Unable to verify the server's certificate. Either it is invalid, or you\n"
JMF 0:082731ede69f 283 "didn't set ca_file or ca_path to an appropriate value. Alternatively,\n"
JMF 0:082731ede69f 284 "you may want to use auth_mode=optional for testing purposes.\n" );
JMF 0:082731ede69f 285 }
JMF 0:082731ede69f 286 FUNC_EXIT_RC(SSL_CONNECTION_ERROR);
JMF 0:082731ede69f 287 }
JMF 0:082731ede69f 288 }
JMF 0:082731ede69f 289
JMF 0:082731ede69f 290 IOT_DEBUG("[ Protocol is %s ]\n[ Ciphersuite is %s ]\n", mbedtls_ssl_get_version(&(tlsDataParams->ssl)),
JMF 0:082731ede69f 291 mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl)));
JMF 0:082731ede69f 292 if((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) {
JMF 0:082731ede69f 293 IOT_DEBUG("[Record expansion is %d]", ret);
JMF 0:082731ede69f 294 }
JMF 0:082731ede69f 295 else{
JMF 0:082731ede69f 296 IOT_DEBUG("[Record expansion is unknown (compression)]");
JMF 0:082731ede69f 297 }
JMF 0:082731ede69f 298 IOT_DEBUG("Verifying peer X.509 certificate...");
JMF 0:082731ede69f 299
JMF 0:082731ede69f 300 if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) {
JMF 0:082731ede69f 301 if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) {
JMF 0:082731ede69f 302 IOT_ERROR(" FAIL\n");
JMF 0:082731ede69f 303 mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", tlsDataParams->flags);
JMF 0:082731ede69f 304 IOT_ERROR("%s\n", vrfy_buf);
JMF 0:082731ede69f 305 ret = SSL_CONNECTION_ERROR;
JMF 0:082731ede69f 306 } else {
JMF 0:082731ede69f 307 IOT_DEBUG("Verified OK\n");
JMF 0:082731ede69f 308 ret = AWS_SUCCESS;
JMF 0:082731ede69f 309 }
JMF 0:082731ede69f 310 } else {
JMF 0:082731ede69f 311 IOT_DEBUG("Server Verification skipped\n");
JMF 0:082731ede69f 312 ret = AWS_SUCCESS;
JMF 0:082731ede69f 313 }
JMF 0:082731ede69f 314
JMF 0:082731ede69f 315 #ifdef ENABLE_IOT_DEBUG
JMF 0:082731ede69f 316 if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) {
JMF 0:082731ede69f 317 unsigned char buf[MBEDTLS_DEBUG_BUFFER_SIZE];
JMF 0:082731ede69f 318 IOT_DEBUG("Peer certificate information ...\n");
JMF 0:082731ede69f 319 mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)));
JMF 0:082731ede69f 320 IOT_DEBUG("%s", buf);
JMF 0:082731ede69f 321 }
JMF 0:082731ede69f 322 #endif
JMF 0:082731ede69f 323
JMF 0:082731ede69f 324 mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), IOT_SSL_READ_TIMEOUT);
JMF 0:082731ede69f 325
JMF 0:082731ede69f 326 FUNC_EXIT_RC((IoT_Error_t) ret);
JMF 0:082731ede69f 327 }
JMF 0:082731ede69f 328
JMF 0:082731ede69f 329 IoT_Error_t iot_tls_write(Network *pNetwork, unsigned char *pMsg, size_t len, awsTimer *timer, size_t *written_len)
JMF 0:082731ede69f 330 {
JMF 0:082731ede69f 331 size_t written_so_far;
JMF 0:082731ede69f 332 bool isErrorFlag = false;
JMF 0:082731ede69f 333 int frags;
JMF 0:082731ede69f 334 int ret = 0;
JMF 0:082731ede69f 335 TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams);
JMF 0:082731ede69f 336
JMF 0:082731ede69f 337 FUNC_ENTRY;
JMF 0:082731ede69f 338 for(written_so_far = 0, frags = 0;
JMF 0:082731ede69f 339 written_so_far < len && !has_timer_expired(timer); written_so_far += ret, frags++) {
JMF 0:082731ede69f 340 while(!has_timer_expired(timer) &&
JMF 0:082731ede69f 341 (ret = mbedtls_ssl_write(&(tlsDataParams->ssl), pMsg + written_so_far, len - written_so_far)) <= 0) {
JMF 0:082731ede69f 342 if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
JMF 0:082731ede69f 343 IOT_ERROR("FAILED!\n ! mbedtls_ssl_write returned -0x%x\n\n", -ret);
JMF 0:082731ede69f 344 /* All other negative return values indicate connection needs to be reset.
JMF 0:082731ede69f 345 * Will be caught in ping request so ignored here */
JMF 0:082731ede69f 346 isErrorFlag = true;
JMF 0:082731ede69f 347 break;
JMF 0:082731ede69f 348 }
JMF 0:082731ede69f 349 }
JMF 0:082731ede69f 350 if(isErrorFlag) {
JMF 0:082731ede69f 351 break;
JMF 0:082731ede69f 352 }
JMF 0:082731ede69f 353 }
JMF 0:082731ede69f 354
JMF 0:082731ede69f 355 *written_len = written_so_far;
JMF 0:082731ede69f 356
JMF 0:082731ede69f 357 if(isErrorFlag) {
JMF 0:082731ede69f 358 FUNC_EXIT_RC(NETWORK_SSL_WRITE_ERROR);
JMF 0:082731ede69f 359 } else if(has_timer_expired(timer) && written_so_far != len) {
JMF 0:082731ede69f 360 FUNC_EXIT_RC(NETWORK_SSL_WRITE_TIMEOUT_ERROR);
JMF 0:082731ede69f 361 }
JMF 0:082731ede69f 362
JMF 0:082731ede69f 363 FUNC_EXIT_RC(AWS_SUCCESS);
JMF 0:082731ede69f 364 }
JMF 0:082731ede69f 365
JMF 0:082731ede69f 366 IoT_Error_t iot_tls_read(Network *pNetwork, unsigned char *pMsg, size_t len, awsTimer *timer, size_t *read_len)
JMF 0:082731ede69f 367 {
JMF 0:082731ede69f 368 mbedtls_ssl_context *ssl = &(pNetwork->tlsDataParams.ssl);
JMF 0:082731ede69f 369 size_t rxLen = 0;
JMF 0:082731ede69f 370 int ret=0;
JMF 0:082731ede69f 371 FUNC_ENTRY;
JMF 0:082731ede69f 372
JMF 0:082731ede69f 373 while (len > 0) {
JMF 0:082731ede69f 374 // This read will timeout after IOT_SSL_READ_TIMEOUT if there's no data to be read
JMF 0:082731ede69f 375
JMF 0:082731ede69f 376 while( ret == 0 && !has_timer_expired(timer) )
JMF 0:082731ede69f 377 ret = mbedtls_ssl_read(ssl, pMsg, len);
JMF 0:082731ede69f 378
JMF 0:082731ede69f 379 if (ret > 0) {
JMF 0:082731ede69f 380 rxLen += ret;
JMF 0:082731ede69f 381 pMsg += ret;
JMF 0:082731ede69f 382 len -= ret;
JMF 0:082731ede69f 383 }
JMF 0:082731ede69f 384 else if (ret == 0 || (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != MBEDTLS_ERR_SSL_TIMEOUT)) {
JMF 0:082731ede69f 385 FUNC_EXIT_RC(NETWORK_SSL_READ_ERROR);
JMF 0:082731ede69f 386 }
JMF 0:082731ede69f 387 }
JMF 0:082731ede69f 388
JMF 0:082731ede69f 389 if (len == 0) {
JMF 0:082731ede69f 390 *read_len = rxLen;
JMF 0:082731ede69f 391 FUNC_EXIT_RC(AWS_SUCCESS);
JMF 0:082731ede69f 392 }
JMF 0:082731ede69f 393
JMF 0:082731ede69f 394 if (rxLen == 0) {
JMF 0:082731ede69f 395 FUNC_EXIT_RC(NETWORK_SSL_NOTHING_TO_READ);
JMF 0:082731ede69f 396 } else {
JMF 0:082731ede69f 397 FUNC_EXIT_RC(NETWORK_SSL_READ_TIMEOUT_ERROR);
JMF 0:082731ede69f 398 }
JMF 0:082731ede69f 399 }
JMF 0:082731ede69f 400
JMF 0:082731ede69f 401 IoT_Error_t iot_tls_disconnect(Network *pNetwork)
JMF 0:082731ede69f 402 {
JMF 0:082731ede69f 403 mbedtls_ssl_context *ssl = &(pNetwork->tlsDataParams.ssl);
JMF 0:082731ede69f 404 int ret = 0;
JMF 0:082731ede69f 405 FUNC_ENTRY;
JMF 0:082731ede69f 406 do {
JMF 0:082731ede69f 407 ret = mbedtls_ssl_close_notify(ssl);
JMF 0:082731ede69f 408 } while(ret == MBEDTLS_ERR_SSL_WANT_WRITE);
JMF 0:082731ede69f 409
JMF 0:082731ede69f 410 /* All other negative return values indicate connection needs to be reset.
JMF 0:082731ede69f 411 * No further action required since this is disconnect call */
JMF 0:082731ede69f 412
JMF 0:082731ede69f 413 FUNC_EXIT_RC(AWS_SUCCESS);
JMF 0:082731ede69f 414 }
JMF 0:082731ede69f 415
JMF 0:082731ede69f 416 IoT_Error_t iot_tls_destroy(Network *pNetwork)
JMF 0:082731ede69f 417 {
JMF 0:082731ede69f 418 TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams);
JMF 0:082731ede69f 419 FUNC_ENTRY;
JMF 0:082731ede69f 420
JMF 0:082731ede69f 421 mbedtls_aws_free(&(tlsDataParams->server_fd));
JMF 0:082731ede69f 422
JMF 0:082731ede69f 423 mbedtls_x509_crt_free(&(tlsDataParams->clicert));
JMF 0:082731ede69f 424 mbedtls_x509_crt_free(&(tlsDataParams->cacert));
JMF 0:082731ede69f 425 mbedtls_pk_free(&(tlsDataParams->pkey));
JMF 0:082731ede69f 426 mbedtls_ssl_free(&(tlsDataParams->ssl));
JMF 0:082731ede69f 427 mbedtls_ssl_config_free(&(tlsDataParams->conf));
JMF 0:082731ede69f 428 mbedtls_ctr_drbg_free(&(tlsDataParams->ctr_drbg));
JMF 0:082731ede69f 429 mbedtls_entropy_free(&(tlsDataParams->entropy));
JMF 0:082731ede69f 430
JMF 0:082731ede69f 431 FUNC_EXIT_RC(AWS_SUCCESS);
JMF 0:082731ede69f 432 }
JMF 0:082731ede69f 433
JMF 0:082731ede69f 434