Jim Flynn
/
aws-iot-device-sdk-mbed-c
Changes to enabled on-line compiler
platform/mbedtls/network_mbedtls_wrapper.cpp@0:082731ede69f, 2018-05-30 (annotated)
- Committer:
- JMF
- Date:
- Wed May 30 20:59:51 2018 +0000
- Revision:
- 0:082731ede69f
Initial commit
Who changed what in which revision?
User | Revision | Line number | New 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 |