mirror of https://github.com/ARMmbed/mbed-os.git
2451 lines
81 KiB
C
2451 lines
81 KiB
C
/*
|
|
* Copyright (c) 2013-2019, Arm Limited and affiliates.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#include "nsconfig.h"
|
|
#include "ns_types.h"
|
|
#ifdef PANA
|
|
#include "string.h"
|
|
#include "Core/include/ns_address_internal.h"
|
|
#include "Core/include/ns_buffer.h"
|
|
#ifdef ECC
|
|
#include "libX509_V3.h"
|
|
#include "ecc.h"
|
|
#endif
|
|
#include "randLIB.h"
|
|
#include "Core/include/ns_socket.h"
|
|
//#include "6LoWPAN/Bootstraps/network_lib.h"
|
|
#include "shalib.h"
|
|
#include "Security/TLS/tls_lib.h"
|
|
#include "Security/TLS/tls_ccm_crypt.h"
|
|
#include "Security/Common/sec_lib.h"
|
|
#include "nsdynmemLIB.h"
|
|
#include "net_nvm_api.h"
|
|
#include "Security/PANA/pana.h"
|
|
#include "Security/PANA/pana_internal_api.h"
|
|
#include "ns_trace.h"
|
|
#include "common_functions.h"
|
|
#include "net_interface.h"
|
|
|
|
#define TRACE_GROUP "TLSl"
|
|
|
|
typedef struct tls_psk_key_ {
|
|
uint16_t key_id;
|
|
uint8_t psk_key[16];
|
|
ns_list_link_t link;
|
|
} tls_psk_key_t;
|
|
|
|
static NS_LIST_DEFINE(tls_psk_list, tls_psk_key_t, link);
|
|
|
|
NS_LARGE tls_header_t tls_header;
|
|
NS_LARGE tls_msg_t tls_msg;
|
|
|
|
#ifdef ECC
|
|
|
|
tls_ecc_heap_t *ecc_allocate_ram(void);
|
|
static uint8_t tls_parse_certificate(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite);
|
|
static uint8_t tls_parse_certificate_verify(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite);
|
|
static uint8_t ecc_verify_calculate_hash(sec_suite_t *tls_suite);
|
|
void tls_ecc_reverse_hash(uint8_t *ptr);
|
|
uint8_t tls_write_signature_parameters(uint8_t *ptr, uint8_t *signature_parameter, uint8_t leadin_zeros);
|
|
uint8_t tls_parse_certificate_request(uint8_t *ptr, uint16_t len);
|
|
static uint8_t tls_parse_client_key_exchange(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite);
|
|
static uint8_t tls_parse_server_key_exchange(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite);
|
|
|
|
#endif
|
|
|
|
static uint8_t *tls_set_client_key_excange(uint8_t *ptr, sec_suite_t *tls_suite);
|
|
static uint8_t tls_parse_server_hello(uint8_t *ptr, sec_suite_t *tls_suite);
|
|
#ifdef PANA_SERVER_API
|
|
static uint8_t tls_parse_client_hello(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite);
|
|
#endif
|
|
static tls_psk_key_t *tls_get_key(uint16_t key_id);
|
|
|
|
tls_session_t *amr_tls_session_allocate(void)
|
|
{
|
|
tls_session_t *t_session = 0;
|
|
t_session = ns_dyn_mem_alloc(sizeof(tls_session_t));
|
|
if (t_session) {
|
|
memset(t_session, 0, sizeof(tls_session_t));
|
|
}
|
|
return t_session;
|
|
}
|
|
|
|
void arm_tls_session_clear(tls_session_t *t_session)
|
|
{
|
|
if (t_session->tls_heap) {
|
|
tls_heap_free(t_session->tls_heap);
|
|
t_session->tls_heap = NULL;
|
|
}
|
|
}
|
|
|
|
static tls_heap_t *tls_heap_structure_allocate(void)
|
|
{
|
|
tls_heap_t *heap_ptr = (tls_heap_t *) ns_dyn_mem_temporary_alloc(sizeof(tls_heap_t));
|
|
if (heap_ptr) {
|
|
memset(heap_ptr, 0, sizeof(tls_heap_t));
|
|
}
|
|
return heap_ptr;
|
|
}
|
|
|
|
int8_t arm_tls_add_psk_key(const uint8_t *key_ptr, uint16_t key_id)
|
|
{
|
|
tls_psk_key_t *key_entry = tls_get_key(key_id);
|
|
|
|
if (key_ptr == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
/* If key with given ID already exists, remove old */
|
|
if (key_entry) {
|
|
arm_tls_remove_psk_key(key_id);
|
|
key_entry = NULL;
|
|
}
|
|
|
|
/* Make new entry */
|
|
key_entry = ns_dyn_mem_alloc(sizeof(tls_psk_key_t));
|
|
if (key_entry == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
memcpy(key_entry->psk_key, key_ptr, 16);
|
|
key_entry->key_id = key_id;
|
|
|
|
ns_list_add_to_end(&tls_psk_list, key_entry);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int8_t arm_tls_check_key(uint16_t key_id)
|
|
{
|
|
if (tls_get_key(key_id) == NULL) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int8_t arm_tls_remove_psk_key(uint16_t key_id)
|
|
{
|
|
tls_psk_key_t *key_to_remove = tls_get_key(key_id);
|
|
|
|
if (key_to_remove == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
ns_list_remove(&tls_psk_list, key_to_remove);
|
|
|
|
ns_dyn_mem_free(key_to_remove);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* returns key entry, null if not found */
|
|
static tls_psk_key_t *tls_get_key(uint16_t key_id)
|
|
{
|
|
ns_list_foreach(tls_psk_key_t, entry, &tls_psk_list) {
|
|
if (entry->key_id == key_id) {
|
|
return entry;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
void tls_finnish_copy(uint8_t *ptr, tls_heap_t *heap_ptr)
|
|
{
|
|
tls_msg_t *tmp_msg = tls_msg_ptr_get();
|
|
tmp_msg->len = 12;
|
|
tmp_msg->msg_ptr = ptr;
|
|
tls_handshake_copy(tmp_msg, heap_ptr);
|
|
|
|
}
|
|
|
|
static uint8_t tls_parse_client_hello(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite)
|
|
{
|
|
uint8_t ret_val = 0, i = 0;
|
|
uint16_t tls_version;
|
|
tls_version = common_read_16_bit(ptr);
|
|
ptr += 2;
|
|
if (tls_version == TLS_1_2_VERSION) {
|
|
uint8_t id_len;
|
|
tls_heap_t *thep = tls_suite->tls_session->tls_heap;
|
|
memcpy((thep->tls_hello_random + CLIENT_HELLO_PTR), ptr, 32);
|
|
ptr += 32;
|
|
//skip sesion id
|
|
id_len = *ptr++;
|
|
len -= 35;
|
|
if (id_len < 33 && (len > id_len + 3)) {
|
|
if (id_len == 0) {
|
|
tr_debug("Fisrt Time generate ID!!");
|
|
len -= 2;
|
|
tls_session_id_genrate(tls_suite->tls_session->tls_session_id, 4);
|
|
tls_suite->tls_session->id_length = 4;
|
|
} else {
|
|
if (tls_suite->tls_session->id_length == id_len) {
|
|
if (memcmp(tls_suite->tls_session->tls_session_id, ptr, id_len) == 0) {
|
|
tr_debug("Generate new Session");
|
|
tls_session_id_genrate(tls_suite->tls_session->tls_session_id, 4);
|
|
tls_suite->tls_session->id_length = 4;
|
|
|
|
}
|
|
}
|
|
|
|
if (ret_val != 0) {
|
|
tr_debug("TLS SESSION ID FAIL");
|
|
return 0;
|
|
}
|
|
ptr += id_len;
|
|
len -= id_len;
|
|
len -= 1;
|
|
}
|
|
ptr++;
|
|
|
|
id_len = *ptr++;
|
|
ret_val = 0;
|
|
|
|
while (id_len) {
|
|
if (len < 2) {
|
|
tr_debug("Cor Client hello pack");
|
|
return 0;
|
|
}
|
|
uint16_t tls_ciphersuite = common_read_16_bit(ptr);
|
|
switch (tls_ciphersuite) {
|
|
case TLS_PSK_WITH_AES_128_CCM_8:
|
|
tr_debug("Client Sup PSK");
|
|
ret_val |= SEC_CIPHERSUITE_PSK;
|
|
break;
|
|
#ifdef ECC
|
|
case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
|
|
thep->client_knows_standard_ecc_ciphersuite = true;
|
|
/* no break */
|
|
/* fall through */
|
|
case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8_COMPAT:
|
|
tr_debug("Client Sup ECC");
|
|
ret_val |= SEC_CIPHERSUITE_ECC;
|
|
break;
|
|
#endif
|
|
default:
|
|
tr_debug("Un Sup Suite: %04" PRIx16, tls_ciphersuite);
|
|
break;
|
|
}
|
|
ptr += 2;
|
|
id_len -= 2;
|
|
len -= 2;
|
|
|
|
}
|
|
ret_val &= tls_suite->supported_chipher_suites;
|
|
if (ret_val) {
|
|
tr_debug("Client pack TRUE");
|
|
|
|
if (ret_val & SEC_CIPHERSUITE_ECC) {
|
|
thep->tls_chipher_mode = CHIPHER_ECC;
|
|
} else {
|
|
thep->tls_chipher_mode = CHIPHER_PSK;
|
|
}
|
|
} else {
|
|
tr_debug("CipherSuite Err");
|
|
i = 2;
|
|
}
|
|
} else {
|
|
tr_debug("Session ID length Fail: %02x", *ptr);
|
|
i = 4;
|
|
}
|
|
} else {
|
|
i = 3;
|
|
}
|
|
if (i) {
|
|
tr_debug("%02x", i);
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
|
|
uint8_t tls_parse_server_hello(uint8_t *ptr, sec_suite_t *tls_suite)
|
|
{
|
|
uint8_t ret_val = 0, i = 0;
|
|
uint16_t tls_version;
|
|
tls_version = common_read_16_bit(ptr);
|
|
ptr += 2;
|
|
if (tls_version == TLS_1_2_VERSION) {
|
|
uint8_t id_len;
|
|
tls_heap_t *thep = tls_suite->tls_session->tls_heap;
|
|
if (thep == 0) {
|
|
return 0;
|
|
}
|
|
memcpy((thep->tls_hello_random + SERVER_HELLO_PTR), ptr, 32);
|
|
ptr += 32;
|
|
//skip sesion id
|
|
id_len = *ptr++;
|
|
if (id_len < 33) {
|
|
tls_suite->tls_session->id_length = id_len;
|
|
memcpy(tls_suite->tls_session->tls_session_id, ptr, id_len);
|
|
ptr += id_len;
|
|
uint16_t tls_cipher_suite = common_read_16_bit(ptr);
|
|
switch (tls_cipher_suite) {
|
|
case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
|
|
case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8_COMPAT:
|
|
tr_debug("ECC CipherSuite");
|
|
ret_val = 2;
|
|
thep->tls_chipher_mode = CHIPHER_ECC;
|
|
break;
|
|
case TLS_PSK_WITH_AES_128_CCM_8:
|
|
tr_debug("PSK CipherSuite");
|
|
ret_val = 1;
|
|
thep->tls_chipher_mode = CHIPHER_PSK;
|
|
tls_ecc_heap_free(thep);
|
|
break;
|
|
default:
|
|
tr_debug("CipherSuite Err: %04x", tls_cipher_suite);
|
|
ptr += 2;
|
|
i = 2;
|
|
break;
|
|
}
|
|
} else {
|
|
tr_debug("Session ID length Fail: %02x", *ptr);
|
|
i = 4;
|
|
}
|
|
} else {
|
|
i = 3;
|
|
}
|
|
if (i) {
|
|
tr_debug("%02x", i);
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
|
|
void tls_alert_build(buffer_t *buf, uint8_t alert)
|
|
{
|
|
tr_debug("TTLs TX:Alert");
|
|
//Build Client Hello
|
|
buffer_data_clear(buf);
|
|
buffer_push_uint8(buf, TLS_ALERT_TYPE);
|
|
buffer_push_uint16(buf, TLS_1_2_VERSION);
|
|
buffer_push_uint16(buf, 0x0002); //Length
|
|
|
|
if (alert == ALERT_CLOSE) {
|
|
buffer_push_uint8(buf, 1); //Mean 2=Fatal, 1=warming
|
|
} else {
|
|
buffer_push_uint8(buf, 2); //Mean 2=Fatal, 1=warming
|
|
}
|
|
buffer_push_uint8(buf, alert);
|
|
}
|
|
|
|
#ifdef PANA_SERVER_API
|
|
void tls_server_hello_build(buffer_t *buf, sec_suite_t *tls_suite)
|
|
{
|
|
uint16_t tls_len = 0;
|
|
uint8_t *ptr;
|
|
tls_msg_t *tmp_msg = tls_msg_ptr_get();
|
|
tr_debug("TTLs TX:Server Hello");
|
|
//Build Client Hello
|
|
buffer_data_clear(buf);
|
|
ptr = buffer_data_pointer(buf);
|
|
*ptr++ = TLS_HANDSHAKE;
|
|
ptr = common_write_16_bit(TLS_1_2_VERSION, ptr);
|
|
ptr = common_write_16_bit(tls_len, ptr);
|
|
|
|
//for Hash calculation
|
|
tmp_msg->msg_ptr = ptr + 4;
|
|
ptr = tls_build_server_hello_msg(ptr, tls_suite->tls_session);
|
|
buffer_data_end_set(buf, ptr);
|
|
|
|
tls_len = buffer_data_length(buf);
|
|
tls_len -= 9;
|
|
tmp_msg->len = tls_len;
|
|
tls_handshake_copy(tmp_msg, tls_suite->tls_session->tls_heap);
|
|
|
|
tls_len += 4;
|
|
ptr = buffer_data_pointer(buf);
|
|
ptr += 3;
|
|
ptr = common_write_16_bit(tls_len, ptr);
|
|
}
|
|
#endif
|
|
|
|
void tls_prepare_change_chipher_spec(sec_suite_t *tls_suite)
|
|
{
|
|
tls_heap_t *theap = tls_suite->tls_session->tls_heap;
|
|
bool server;
|
|
tls_build_client_verify_payload(theap);
|
|
if ((tls_suite->setups & TLS_SERVER_MODE) == 0) {
|
|
server = false;
|
|
if ((tls_suite->setups & TLS_HANSHAKE_HASH) == 0) {
|
|
tls_finnish_copy(theap->hash_buf + 4, theap);
|
|
tls_suite->setups |= TLS_HANSHAKE_HASH;
|
|
}
|
|
|
|
} else {
|
|
server = true;
|
|
}
|
|
|
|
tls_ccm_data_encrypt(theap->hash_buf, 16, tls_suite->tls_session->key_expansion, tls_suite->tls_session->tls_nonce_explit, TLS_HANDSHAKE, server);
|
|
}
|
|
|
|
|
|
static buffer_t *tls_down(buffer_t *buf)
|
|
{
|
|
uint16_t tls_len;
|
|
if ((buf = buffer_headroom(buf, 5)) != 0) {
|
|
uint8_t *ptr;
|
|
buffer_data_reserve_header(buf, 5);
|
|
ptr = buffer_data_pointer(buf);
|
|
tls_len = buffer_data_length(buf);
|
|
tls_len -= 5; //Cut Flags byte off
|
|
|
|
*ptr++ = TLS_HANDSHAKE;
|
|
ptr = common_write_16_bit(TLS_1_2_VERSION, ptr);
|
|
ptr = common_write_16_bit(tls_len, ptr);
|
|
}
|
|
return (buf);
|
|
}
|
|
|
|
#ifdef ECC
|
|
|
|
void tls_parse_subject_get_pub_key_from_chain(tls_heap_t *theap, uint8_t rd_ptr)
|
|
{
|
|
uint8_t *ptr = 0;
|
|
certificate_info_t *cer_info = &(theap->rx_ceri_chain.certi_chain[rd_ptr]);
|
|
uint8_t i;
|
|
ptr = cer_info->pub_key_ptr;
|
|
theap->ecc_heap->cert_pub_key.finite = 1;
|
|
theap->ecc_heap->cert_pub_key.invalid = 0;
|
|
|
|
memset(theap->ecc_heap->cert_pub_key.x.data, 0, sizeof(MPint));
|
|
memset(theap->ecc_heap->cert_pub_key.y.data, 0, sizeof(MPint));
|
|
tr_debug("Certificates PUB Key: %s", tr_array(ptr, 64));
|
|
for (i = 0; i < 32; i++) {
|
|
|
|
*((uint8_t *)theap->ecc_heap->cert_pub_key.x.data + i) = *(ptr + 31 - i) ;
|
|
*((uint8_t *)theap->ecc_heap->cert_pub_key.y.data + i) = *(ptr + 63 - i) ;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
uint8_t tls_parse_certificate(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite)
|
|
{
|
|
|
|
uint16_t sub_len = 0;
|
|
uint8_t ret_val = 0;
|
|
tls_heap_t *theap = tls_suite->tls_session->tls_heap;
|
|
//Check Lengths
|
|
if (*ptr++) {
|
|
tr_debug("Too Long len");
|
|
} else {
|
|
sub_len = common_read_16_bit(ptr);
|
|
ptr += 2;
|
|
len -= 3;
|
|
tr_debug("Certi(Chain) Len: %04x", sub_len);
|
|
if (sub_len == 0 || sub_len > len) {
|
|
tr_debug("Cert Base len mis match");
|
|
} else {
|
|
if (x509_v3_certi_chain_analyze(ptr, sub_len, &(theap->rx_ceri_chain)) == 0) {
|
|
tr_debug("Certificate Chain not valid");
|
|
} else {
|
|
tls_parse_subject_get_pub_key_from_chain(theap, 0);
|
|
ret_val = 1;
|
|
}
|
|
}
|
|
}
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
uint8_t tls_parse_server_key_exchange(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite)
|
|
{
|
|
(void)len;
|
|
uint16_t curve_type;
|
|
if (*ptr++ == 3) {
|
|
curve_type = common_read_16_bit(ptr);
|
|
if (curve_type == TLS_NAMED_CURVE_SECP256R1) {
|
|
uint8_t c_len = 0, mode;
|
|
uint16_t sig_algh, signature_len;
|
|
tls_heap_t *theap = tls_suite->tls_session->tls_heap;
|
|
ptr += 2;
|
|
//len -= 5;
|
|
c_len = *ptr++;
|
|
mode = *ptr++;
|
|
|
|
if (mode == 4) {
|
|
c_len--;
|
|
memcpy(theap->ecc_heap->server_public_key, ptr, 64);
|
|
ptr += 64;
|
|
sig_algh = common_read_16_bit(ptr);
|
|
if (sig_algh != TLS_SIG_HASH_ALG_SHA256_ECDSA) {
|
|
tr_debug("tls ser key ex. er");
|
|
return 0;
|
|
}
|
|
ptr += 2;
|
|
signature_len = common_read_16_bit(ptr);
|
|
if (signature_len < 11) {
|
|
return 0;
|
|
}
|
|
ptr += 2;
|
|
if (*ptr++ != 0x30) {
|
|
return 0;
|
|
}
|
|
if (*ptr++ < 9) {
|
|
return 0;
|
|
}
|
|
if (*ptr++ != 2) {
|
|
return 0;
|
|
} else {
|
|
uint8_t rslen;
|
|
//uint8_t i;
|
|
theap->key_signature_ptr = ptr;
|
|
rslen = *ptr++;
|
|
|
|
if (rslen > 33) {
|
|
return 0;
|
|
} else if (rslen == 0) {
|
|
return 0;
|
|
} else if (rslen == 33) {
|
|
|
|
ptr++;
|
|
rslen = 32;
|
|
|
|
}
|
|
if (theap->ecc_heap->sgnt == 0) {
|
|
theap->ecc_heap->sgnt = ECDSA_get_signature();
|
|
}
|
|
if (!theap->ecc_heap->sgnt) {
|
|
return 0;
|
|
}
|
|
|
|
ptr += rslen;
|
|
if (*ptr++ != 2) {
|
|
return 0;
|
|
}
|
|
|
|
rslen = *ptr++;
|
|
|
|
if (rslen > 33) {
|
|
return 0;
|
|
} else if (rslen == 0) {
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
} else {
|
|
tr_debug("Mode!: %02x", mode);
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#ifdef ECC
|
|
static uint8_t tls_parse_client_key_exchange(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite)
|
|
{
|
|
(void)len;
|
|
uint8_t d_len = 0;
|
|
uint8_t mode = 0;
|
|
d_len = *ptr++;
|
|
mode = *ptr++;
|
|
if (d_len == 65 && mode == 4) {
|
|
tls_heap_t *theap = tls_suite->tls_session->tls_heap;
|
|
tr_debug("Valid Client ECC curve:");
|
|
memcpy(theap->ecc_heap->client_public_key, ptr, 64);
|
|
tr_debug("%s", tr_array(ptr, 64));
|
|
return 1;
|
|
} else {
|
|
tr_debug("Len: %02x, mode fail: %02x", d_len, mode);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
void tls_read_certi_signature(tls_heap_t *theap, uint8_t certificate)
|
|
{
|
|
uint8_t rslen = 0;
|
|
uint8_t *ptr = 0;
|
|
if (certificate) {
|
|
//
|
|
certificate_info_t *cer_info = &(theap->rx_ceri_chain.certi_chain[theap->rx_ceri_chain.rd_ptr]);
|
|
ptr = cer_info->signature_ptr;
|
|
} else {
|
|
ptr = theap->key_signature_ptr;
|
|
}
|
|
memset(theap->ecc_heap->sgnt->m_R.data, 0, sizeof(MPint));
|
|
memset(theap->ecc_heap->sgnt->m_s.data, 0, sizeof(MPint));
|
|
rslen = x509_v3_parse_signature_parameter(ptr, ((uint8_t *)theap->ecc_heap->sgnt->m_R.data));
|
|
ptr += rslen;
|
|
ptr++;
|
|
x509_v3_parse_signature_parameter(ptr, ((uint8_t *)theap->ecc_heap->sgnt->m_s.data));
|
|
|
|
}
|
|
|
|
#ifdef ECC
|
|
static uint8_t tls_parse_certificate_verify(uint8_t *ptr, uint16_t len, sec_suite_t *tls_suite)
|
|
{
|
|
(void)len;
|
|
uint16_t sig_algh, sig_len;
|
|
tls_heap_t *theap = tls_suite->tls_session->tls_heap;
|
|
|
|
sig_algh = common_read_16_bit(ptr);
|
|
if (sig_algh != TLS_SIG_HASH_ALG_SHA256_ECDSA) {
|
|
tr_debug("tls ser key ex. er2");
|
|
return 0;
|
|
}
|
|
ptr += 2;
|
|
sig_len = common_read_16_bit(ptr);
|
|
if (sig_len < 11) {
|
|
return 0;
|
|
}
|
|
ptr += 2;
|
|
if (*ptr++ != 0x30) {
|
|
return 0;
|
|
}
|
|
if (*ptr++ < 9) {
|
|
return 0;
|
|
}
|
|
if (theap->ecc_heap) {
|
|
if (theap->ecc_heap->sgnt == 0) {
|
|
tr_debug("Allocate SIG");
|
|
theap->ecc_heap->sgnt = ECDSA_get_signature();
|
|
|
|
if (!theap->ecc_heap->sgnt) {
|
|
tr_debug("Signature Allocate Fail");
|
|
return 0;
|
|
}
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
memset(theap->ecc_heap->sgnt->m_R.data, 0, sizeof(MPint));
|
|
memset(theap->ecc_heap->sgnt->m_s.data, 0, sizeof(MPint));
|
|
|
|
|
|
if (*ptr++ != 2) {
|
|
return 0;
|
|
} else {
|
|
uint8_t rslen = 0;
|
|
theap->key_signature_ptr = ptr;
|
|
rslen = x509_v3_parse_signature_parameter(ptr, ((uint8_t *)theap->ecc_heap->sgnt->m_R.data));
|
|
if (rslen == 0) {
|
|
return 0;
|
|
}
|
|
ptr += rslen;
|
|
}
|
|
if (*ptr++ != 2) {
|
|
return 0;
|
|
} else {
|
|
uint8_t rslen = 0;
|
|
rslen = x509_v3_parse_signature_parameter(ptr, ((uint8_t *)theap->ecc_heap->sgnt->m_s.data));
|
|
if (rslen == 0) {
|
|
return 0;
|
|
}
|
|
//ptr += rslen;
|
|
}
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
tls_ecc_heap_t *ecc_allocate_ram(void)
|
|
{
|
|
tls_ecc_heap_t *heap_ptr = (tls_ecc_heap_t *) ns_dyn_mem_temporary_alloc(sizeof(tls_ecc_heap_t));
|
|
|
|
if (heap_ptr == 0) {
|
|
tr_debug("ECC variable malloc fail");
|
|
} else {
|
|
//heap_scan();
|
|
heap_ptr->sgnt = ecc_get_ecdsa_signature();
|
|
if (!heap_ptr->sgnt) {
|
|
tr_debug("Signature Fail");
|
|
ns_dyn_mem_free(heap_ptr);
|
|
heap_ptr = 0;
|
|
}
|
|
}
|
|
return heap_ptr;
|
|
|
|
}
|
|
|
|
|
|
uint8_t *tls_client_key_exchange_msg_set(uint8_t *ptr, tls_heap_t *heap_ptr)
|
|
{
|
|
/* Client Key Exchange */
|
|
*ptr++ = TLS_CLIENT_KEY_EXCHANGE;
|
|
ptr = common_write_24_bit(66, ptr);
|
|
ptr = common_write_16_bit(0x4104, ptr);
|
|
//There shuold be calculated case now only test purpose
|
|
memcpy(ptr, heap_ptr->ecc_heap->client_public_key, 64);
|
|
ptr += 64;
|
|
return ptr;
|
|
}
|
|
#endif
|
|
|
|
|
|
uint8_t *tls_set_client_key_excange(uint8_t *ptr, sec_suite_t *tls_suite)
|
|
{
|
|
uint8_t key_id_len = (tls_suite->psk_key_id > 0xFF) ? 2 : 1;
|
|
|
|
/* TLS plaintext header = [type][version][length] */
|
|
*ptr++ = TLS_HANDSHAKE;
|
|
ptr = common_write_16_bit(TLS_1_2_VERSION, ptr);
|
|
ptr = common_write_16_bit(6 + key_id_len, ptr);
|
|
|
|
/* Handshake message [msg_type][length] */
|
|
*ptr++ = TLS_CLIENT_KEY_EXCHANGE;
|
|
ptr = common_write_24_bit(2 + key_id_len, ptr);
|
|
|
|
/* ClientKeyExchange [length][psk_id] */
|
|
ptr = common_write_16_bit(key_id_len, ptr); //len
|
|
if (tls_suite->psk_key_id > 0xFF) {
|
|
*ptr++ = tls_suite->psk_key_id >> 8;
|
|
}
|
|
*ptr++ = tls_suite->psk_key_id;
|
|
|
|
return ptr;
|
|
}
|
|
|
|
uint8_t *tls_build_change_chipher_suite_finnish_msg(uint8_t *ptr, tls_session_t *tls_session)
|
|
{
|
|
*ptr++ = TLS_CHANGE_CIPHER_SPEC;
|
|
ptr = common_write_16_bit(TLS_1_2_VERSION, ptr);
|
|
ptr = common_write_16_bit(1, ptr); //len
|
|
*ptr++ = 1;
|
|
*ptr++ = TLS_HANDSHAKE;
|
|
ptr = common_write_16_bit(TLS_1_2_VERSION, ptr);
|
|
ptr = common_write_16_bit(32, ptr); //len
|
|
//Calculate Verify and MAC (MIC)
|
|
//CCMNONCEEXPLICT //SHuold be 0x0000000000000000 at client side
|
|
|
|
memcpy(ptr, tls_session->tls_nonce_explit, 8); // Dynamic
|
|
ptr += 8;
|
|
//MSG Finished
|
|
memcpy(ptr, tls_session->tls_heap->hash_buf, 24);
|
|
ptr += 24;
|
|
return ptr;
|
|
}
|
|
|
|
void tls_build_client_change_chipher_suite_finnish(buffer_t *buf, sec_suite_t *tls_suite)
|
|
{
|
|
uint8_t *ptr;
|
|
buffer_data_clear(buf);
|
|
ptr = buffer_data_pointer(buf);
|
|
if ((tls_suite->setups & TLS_SERVER_MODE) == 0) {
|
|
ptr = tls_set_client_key_excange(ptr, tls_suite);
|
|
}
|
|
ptr = tls_build_change_chipher_suite_finnish_msg(ptr, tls_suite->tls_session);
|
|
buffer_data_end_set(buf, ptr);
|
|
tr_debug("TLS TX: KEY Exchange");
|
|
}
|
|
#ifdef ECC
|
|
void tls_ecc_verfify_start(sec_suite_t *tls_suite)
|
|
{
|
|
if (ecc_state_idle_check() == ECC_STATUS_OK) {
|
|
tls_heap_t *tls_heap = tls_suite->tls_session->tls_heap;
|
|
uint8_t hash_response = ecc_verify_calculate_hash(tls_suite);
|
|
if (hash_response) {
|
|
tr_debug("HASH calc Fail: %02x", hash_response);
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_INTERNAL);
|
|
} else {
|
|
int8_t ecc_response = ecc_calculate_verify(tls_heap->ecc_heap->sgnt, &(tls_heap->ecc_heap->cert_pub_key), &ecc_operation_done_callback);
|
|
if (ecc_response == ECC_STATUS_OK) {
|
|
tls_heap->ecc_heap->sgnt = 0;
|
|
sec_lib_state_machine_lock(tls_suite, TLS_ECC_MESSAGE_VERIFY);
|
|
sec_ecc_state_save(tls_suite);
|
|
} else {
|
|
tr_debug("calcVerify Fail: %d", ecc_response);
|
|
}
|
|
}
|
|
} else {
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ECC_MESSAGE_VERIFY_START2);
|
|
}
|
|
}
|
|
|
|
|
|
void tls_certificate_signature_verify(sec_suite_t *tls_suite)
|
|
{
|
|
tls_heap_t *tls_heap = tls_suite->tls_session->tls_heap;
|
|
if (ecc_state_idle_check() == ECC_STATUS_OK) {
|
|
uint8_t alert_tx = 0;
|
|
uint8_t chain_analyze_ok = 0;
|
|
if (tls_heap->rx_ceri_chain.rd_ptr + 1 <= tls_heap->rx_ceri_chain.wr_ptr) {
|
|
uint8_t certi_verify = 0;
|
|
certificate_info_t *cer_info = &(tls_heap->rx_ceri_chain.certi_chain[tls_heap->rx_ceri_chain.rd_ptr]);
|
|
|
|
//Verify Cur Certi Signature bye Next Certi PK
|
|
tr_debug("index,Check Signature: rd: %02x, wr: %02x", tls_heap->rx_ceri_chain.rd_ptr, tls_heap->rx_ceri_chain.wr_ptr);
|
|
|
|
if ((tls_heap->rx_ceri_chain.rd_ptr + 1) == tls_heap->rx_ceri_chain.wr_ptr) {
|
|
uint8_t self_signed = 0;
|
|
if (cer_info->issue_len == cer_info->subj_len) {
|
|
if (memcmp(cer_info->issue_ptr, cer_info->subj_ptr, cer_info->issue_len) == 0) {
|
|
self_signed = 1;
|
|
}
|
|
}
|
|
|
|
if (self_signed) {
|
|
certificate_chain_internal_t *temp;
|
|
|
|
temp = sec_cetificate_chain_get(SEC_NWK_AUTHENTICATION_CERTI_CHAIN);
|
|
|
|
tr_debug("SELF Signed. Compare Root");
|
|
if (temp) {
|
|
uint16_t root_len = 0;
|
|
uint8_t root_type = 0;
|
|
const uint8_t *ptr = temp->certi_chain[0];
|
|
uint8_t *root_ptr = cer_info->certi_ptr;
|
|
root_ptr -= 4;
|
|
asn1_parse(root_ptr, &root_len, &root_type);
|
|
alert_tx = 1;
|
|
if ((root_len + 4) == temp->certi_len[0]) {
|
|
if (memcmp(root_ptr, ptr, temp->certi_len[0]) == 0) {
|
|
tr_debug("Trusted Root certificate");
|
|
alert_tx = 0;
|
|
chain_analyze_ok = 1;
|
|
} else {
|
|
tr_debug("Not Trusted Root");
|
|
}
|
|
} else {
|
|
alert_tx = 1;
|
|
}
|
|
} else {
|
|
alert_tx = 1;
|
|
}
|
|
} else {
|
|
|
|
//Compare all ways to Root Certi
|
|
certificate_chain_internal_t *temp;
|
|
|
|
temp = sec_cetificate_chain_get(SEC_NWK_AUTHENTICATION_CERTI_CHAIN);
|
|
if (temp) {
|
|
if (temp->sub_len[0] == cer_info->issue_len) {
|
|
if (memcmp(cer_info->issue_ptr, temp->sub_chain[0], cer_info->issue_len) == 0) {
|
|
tr_debug("Get Root PK");
|
|
tls_heap->rx_ceri_chain.wr_ptr--;
|
|
if (x509_v3_certi_pk_get((uint8_t *)temp->certi_chain[0], &(tls_heap->rx_ceri_chain)) == 0) {
|
|
tr_debug("..fail");
|
|
} else {
|
|
tr_debug("..OK");
|
|
tls_parse_subject_get_pub_key_from_chain(tls_heap, (tls_heap->rx_ceri_chain.rd_ptr));
|
|
certi_verify = 2;
|
|
}
|
|
}
|
|
}
|
|
if (certi_verify == 0) {
|
|
alert_tx = 1;
|
|
tr_debug("Unknow CA");
|
|
}
|
|
} else {
|
|
alert_tx = 1;
|
|
}
|
|
}
|
|
} else {
|
|
|
|
certificate_info_t *cer_sig = &(tls_heap->rx_ceri_chain.certi_chain[tls_heap->rx_ceri_chain.rd_ptr + 1]);
|
|
|
|
if (cer_info->issue_len == cer_sig->subj_len) {
|
|
if (memcmp(cer_info->issue_ptr, cer_sig->subj_ptr, cer_info->issue_len) == 0) {
|
|
certi_verify = 1;
|
|
} else {
|
|
alert_tx = 1;
|
|
tr_debug("Not Valid chain signature subject entry");
|
|
}
|
|
} else {
|
|
alert_tx = 1;
|
|
tr_debug("Not Valid chain signature subject len");
|
|
}
|
|
|
|
|
|
}
|
|
if (certi_verify) {
|
|
//Calc HASH
|
|
memset((uint8_t *)tls_heap->ecc_heap->sgnt->m_m.data, 0, sizeof(MPint));
|
|
ns_sha256(cer_info->certi_ptr, cer_info->certi_len, tls_heap->ecc_heap->sgnt->m_m.data);
|
|
tls_ecc_reverse_hash((uint8_t *)tls_heap->ecc_heap->sgnt->m_m.data);
|
|
|
|
//GET Signature From Cur Certi
|
|
tls_read_certi_signature(tls_heap, 1);
|
|
|
|
//GET PUB KEY from next HOP
|
|
if (certi_verify == 1) {
|
|
tls_parse_subject_get_pub_key_from_chain(tls_heap, (tls_heap->rx_ceri_chain.rd_ptr + 1));
|
|
|
|
}
|
|
|
|
if (ecc_calculate_verify(tls_heap->ecc_heap->sgnt, &tls_heap->ecc_heap->cert_pub_key, &ecc_operation_done_callback) == ECC_STATUS_OK) {
|
|
tls_heap->ecc_heap->sgnt = 0;
|
|
sec_lib_state_machine_lock(tls_suite, TLS_ECC_CERTIFICATE_SIGNATURE_CHECK);
|
|
sec_ecc_state_save(tls_suite);
|
|
tls_heap->rx_ceri_chain.rd_ptr++;
|
|
} else {
|
|
if (tls_heap->ecc_heap->sgnt) {
|
|
ns_dyn_mem_free(tls_heap->ecc_heap->sgnt);
|
|
tls_heap->ecc_heap->sgnt = 0;
|
|
}
|
|
alert_tx = 1;
|
|
|
|
}
|
|
}
|
|
} else {
|
|
chain_analyze_ok = 1;
|
|
}
|
|
|
|
if (chain_analyze_ok) {
|
|
if (tls_heap->signature_temp_buf) {
|
|
//Take Signature
|
|
tls_read_certi_signature(tls_heap, 0);
|
|
if (tls_heap->signature_temp_buf == tls_heap->cert_temp_buf) {
|
|
tls_heap->signature_temp_buf = 0;
|
|
} else {
|
|
if (tls_heap->pointer_types & 2) {
|
|
buffer_free(tls_heap->signature_temp_buf);
|
|
} else {
|
|
ns_dyn_mem_free(tls_heap->signature_temp_buf);
|
|
}
|
|
tls_heap->signature_temp_buf = 0;
|
|
}
|
|
}
|
|
|
|
tr_debug("Certi signature check OK");
|
|
tls_parse_subject_get_pub_key_from_chain(tls_heap, 0);
|
|
|
|
if (tls_heap->rx_ceri_chain.wr_ptr == 0) {
|
|
certificate_info_t *c_ptr = &(tls_heap->rx_ceri_chain.certi_chain[0]);
|
|
if (x509_v3_certi_pk_get((uint8_t *)c_ptr->certi_ptr, &tls_heap->rx_ceri_chain) == 0) {
|
|
tr_debug("Fail read certificate PUB Key");
|
|
} else {
|
|
tls_parse_subject_get_pub_key_from_chain(tls_heap, (tls_heap->rx_ceri_chain.wr_ptr));
|
|
}
|
|
}
|
|
|
|
if (tls_heap->pointer_types & 1) {
|
|
buffer_free(tls_heap->cert_temp_buf);
|
|
} else {
|
|
ns_dyn_mem_free(tls_heap->cert_temp_buf);
|
|
}
|
|
tls_heap->cert_temp_buf = 0;
|
|
|
|
if (tls_suite->setups & TLS_SERVER_MODE) {
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ECC_MESSAGE_SERVER_VERIFY_START);
|
|
} else {
|
|
tr_debug("Start Do Certi Verify calc");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ECC_MESSAGE_VERIFY_START2);
|
|
}
|
|
}
|
|
if (alert_tx) {
|
|
tr_debug("PSK cal fail");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_INTERNAL);
|
|
}
|
|
} else {
|
|
tls_suite->timer = 1;
|
|
}
|
|
}
|
|
|
|
void tls_server_finnish_handle_start(sec_suite_t *tls_suite)
|
|
{
|
|
if (ecc_state_idle_check() == ECC_STATUS_OK) {
|
|
tls_heap_t *tls_heap = tls_suite->tls_session->tls_heap;
|
|
uint8_t alert_tx = 0;
|
|
if (tls_suite->setups & TLS_ECC_CERTIFICATE_VERIFY) {
|
|
memcpy(tls_heap->ecc_heap->sgnt->m_m.data, tls_heap->hash_buf, 32);
|
|
// initialize the rest of MPint as the hash is covering only part of it
|
|
memset(((uint8_t *)tls_heap->ecc_heap->sgnt->m_m.data) + 32, 0, sizeof(MPint) - 32);
|
|
tls_ecc_reverse_hash((uint8_t *)tls_heap->ecc_heap->sgnt->m_m.data);
|
|
|
|
if (ecc_calculate_verify(tls_heap->ecc_heap->sgnt, &tls_heap->ecc_heap->cert_pub_key, &ecc_operation_done_callback) == ECC_STATUS_OK) {
|
|
tls_heap->ecc_heap->sgnt = 0;
|
|
sec_lib_state_machine_lock(tls_suite, TLS_ECC_MESSAGE_VERIFY);
|
|
sec_ecc_state_save(tls_suite);
|
|
} else {
|
|
if (tls_heap->ecc_heap->sgnt) {
|
|
ecc_library_free_pointer(tls_heap->ecc_heap->sgnt);
|
|
//ns_dyn_mem_free(tls_heap->ecc_heap->sgnt);
|
|
tls_heap->ecc_heap->sgnt = 0;
|
|
}
|
|
alert_tx = 1;
|
|
|
|
}
|
|
} else {
|
|
if (tls_ecc_start_premaster_secret(0, tls_suite) == 0) {
|
|
alert_tx = 1;
|
|
}
|
|
}
|
|
if (alert_tx) {
|
|
tr_debug("PSK cal fail");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_INTERNAL);
|
|
}
|
|
} else {
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ECC_MESSAGE_SERVER_VERIFY_START);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef PANA_SERVER_API
|
|
static buffer_t *tls_verify_handler(uint8_t certi_rx, tls_header_t *tls_header_ptr, buffer_t *buf, sec_suite_t *tls_suite)
|
|
{
|
|
(void) certi_rx;
|
|
tls_heap_t *tls_heap = tls_suite->tls_session->tls_heap;
|
|
tls_heap->client_verify_buf_len = tls_header_ptr->length;
|
|
if (tls_heap->client_verify_buf) {
|
|
tr_debug("Free Server Client 1r");
|
|
ns_dyn_mem_free(tls_heap->client_verify_buf);
|
|
tls_heap->client_verify_buf = 0;
|
|
}
|
|
tls_heap->client_verify_buf = ns_dyn_mem_alloc(tls_header_ptr->length);
|
|
if (tls_heap->client_verify_buf) {
|
|
memcpy(tls_heap->client_verify_buf, tls_header_ptr->ptr, tls_header_ptr->length);
|
|
|
|
#ifdef ECC
|
|
if (tls_heap->tls_chipher_mode == CHIPHER_ECC) {
|
|
|
|
if (certi_rx) {
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ECC_MESSAGE_SERVER_VERIFY_START);
|
|
tr_debug("Certi RX > 0");
|
|
if (tls_suite->tls_session->tls_heap) {
|
|
uint8_t free_buf = 1;
|
|
if (certi_rx & 1) {
|
|
if (tls_heap->cert_temp_buf == 0) {
|
|
tls_heap->pointer_types |= 1;
|
|
tls_heap->cert_temp_buf = buf;
|
|
free_buf = 0;
|
|
}
|
|
}
|
|
if (certi_rx & 2) {
|
|
if (tls_heap->signature_temp_buf == 0) {
|
|
tls_heap->pointer_types |= 2;
|
|
tls_heap->signature_temp_buf = buf;
|
|
free_buf = 0;
|
|
}
|
|
}
|
|
|
|
if (free_buf == 0) {
|
|
buf = NULL;
|
|
}
|
|
}
|
|
|
|
}
|
|
if (buf) {
|
|
buf = buffer_free(buf);
|
|
}
|
|
|
|
} else
|
|
#endif
|
|
{
|
|
tr_debug("Start Server PRF_CALC state");
|
|
sec_prf_state_set(tls_suite);
|
|
}
|
|
} else {
|
|
tr_debug("Heap_error: client verify chiphersuite!!");
|
|
}
|
|
|
|
return (buf);
|
|
}
|
|
#endif
|
|
|
|
static int8_t tls_client_verify_handler(tls_header_t *tls_header_ptr, sec_suite_t *tls_suite)
|
|
{
|
|
if (tls_ccm_data_decrypt(tls_header_ptr->ptr, tls_header_ptr->length, tls_suite->tls_session->key_expansion, TLS_HANDSHAKE, true) == 0) {
|
|
uint8_t *ptr = tls_header_ptr->ptr + 8;
|
|
tls_heap_t *tls_heap = tls_suite->tls_session->tls_heap;
|
|
|
|
if (ptr[0] == TLS_FINISHED && common_read_24_bit(ptr + 1) == 12) {
|
|
ptr += 4;
|
|
//
|
|
tr_debug("Finish RX: %s", tr_array(ptr, 12));
|
|
|
|
memcpy(tls_heap->verify, ptr, 12);
|
|
return 0;
|
|
} else {
|
|
//RETURN error
|
|
tr_debug("No Chiphertext");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
tr_debug("Encode error");
|
|
return -2;
|
|
|
|
}
|
|
|
|
static buffer_t *tls_certificate_buffer_store(buffer_t *buf, uint8_t certi_rx, sec_suite_t *tls_suite)
|
|
{
|
|
if (certi_rx) {
|
|
if (tls_suite->tls_session->tls_heap) {
|
|
uint8_t free_buf = 1;
|
|
tls_heap_t *theap = tls_suite->tls_session->tls_heap;
|
|
if (certi_rx & 1) {
|
|
if (theap->cert_temp_buf == 0) {
|
|
theap->pointer_types |= 1;
|
|
theap->cert_temp_buf = buf;
|
|
free_buf = 0;
|
|
|
|
}
|
|
}
|
|
if (certi_rx & 2) {
|
|
if (theap->signature_temp_buf == 0) {
|
|
theap->pointer_types |= 2;
|
|
theap->signature_temp_buf = buf;
|
|
free_buf = 0;
|
|
}
|
|
}
|
|
if (free_buf == 0) {
|
|
buf = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (buf) {
|
|
buf = buffer_free(buf);
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
buffer_t *tls_client_up(buffer_t *buf, sec_suite_t *tls_suite)
|
|
{
|
|
uint8_t i = 0, certi_rx = 0;
|
|
uint16_t data_len = 0;
|
|
uint8_t alert_case = 0;
|
|
uint8_t *ptr;
|
|
tls_header_t *tls_header_ptr;
|
|
tls_heap_t *tls_heap = tls_suite->tls_session->tls_heap;
|
|
uint8_t algo_ok = 0, j = 0;
|
|
ptr = buffer_data_pointer(buf);
|
|
|
|
i = 1;
|
|
while (buf->buf_ptr < buf->buf_end) {
|
|
data_len = buffer_data_length(buf);
|
|
ptr = buffer_data_pointer(buf);
|
|
tls_header_ptr = NULL;
|
|
|
|
if (data_len >= 5) {
|
|
uint16_t tls_version;
|
|
tls_header.type = *ptr++;
|
|
tls_version = common_read_16_bit(ptr);
|
|
ptr += 2;
|
|
if (tls_version != TLS_1_2_VERSION) {
|
|
tr_debug("Len: %04x", data_len);
|
|
tr_debug("%s", tr_array(ptr, 4));
|
|
alert_case = 4;
|
|
} else {
|
|
tls_header.length = common_read_16_bit(ptr);
|
|
ptr += 2;
|
|
data_len -= 5;
|
|
if (tls_header.length > data_len) {
|
|
alert_case = 5;
|
|
} else {
|
|
tr_debug("Full TLS Record");
|
|
tls_header.ptr = ptr;
|
|
buf->buf_ptr += tls_header.length;
|
|
buf->buf_ptr += 5;
|
|
tls_header_ptr = &tls_header;
|
|
}
|
|
}
|
|
} else {
|
|
alert_case = 5;
|
|
}
|
|
|
|
if (alert_case) {
|
|
tr_debug("TLS Segmentation or datagram error: %02x", alert_case);
|
|
buf->buf_ptr = buf->buf_end;
|
|
//SET Alert Case
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_INTERNAL);
|
|
return buffer_free(buf);
|
|
}
|
|
|
|
if (tls_header_ptr) {
|
|
if (tls_header_ptr->type == TLS_HANDSHAKE && (tls_heap != 0)) {
|
|
tr_debug("Type:Handshake");
|
|
if (tls_suite->state == TLS_CHANGE_CHIPHER) {
|
|
if (tls_header_ptr->length < 32) {
|
|
tr_debug("Too short Chiher Text");
|
|
} else if ((algo_ok & 0x20) && (tls_suite->state == PRF_CALC)) {
|
|
tr_debug("Drop Client RE TX");
|
|
/*tls_text_cnt = */j = 1;
|
|
} else {
|
|
int8_t returnCode = tls_client_verify_handler(tls_header_ptr, tls_suite);
|
|
if (returnCode == 0) {
|
|
algo_ok |= 0x10;
|
|
sec_lib_state_machine_trig(tls_suite, TLS_FINISH);
|
|
j = 1;
|
|
} else if (returnCode == -1) {
|
|
sec_lib_state_machine_trig(tls_suite, PANA_ERROR);
|
|
return buffer_free(buf);
|
|
} else {
|
|
i = 5;
|
|
sec_lib_state_machine_trig(tls_suite, PANA_ERROR);
|
|
break;
|
|
}
|
|
|
|
//Set Back Originals
|
|
tls_header_ptr->ptr -= 8;
|
|
tls_header_ptr->length += 16;
|
|
}
|
|
} else {
|
|
uint8_t tls_msg_cnt = 0;
|
|
tls_msg_t *tls_msg_ptr = 0;
|
|
if (algo_ok != 0x18) {
|
|
tls_msg_cnt = tls_msg_analyzy(tls_header_ptr->ptr, tls_header_ptr->length);
|
|
j = 0;
|
|
}
|
|
ptr = tls_header_ptr->ptr;
|
|
while (j < tls_msg_cnt) {
|
|
tls_msg_ptr = tls_msg_get(ptr);
|
|
|
|
switch (tls_msg_ptr->type) {
|
|
case TLS_SERVER_HELLO:
|
|
if (tls_msg_ptr->len >= 38) {
|
|
if (tls_suite->state == TLS_INIT) {
|
|
if (tls_parse_server_hello(tls_msg_ptr->msg_ptr, tls_suite)) {
|
|
|
|
uint8_t switch_state = 0;
|
|
tr_debug("TLS:S_Hello OK");
|
|
if (tls_heap->tls_chipher_mode != CHIPHER_ECC) {
|
|
algo_ok |= 1;
|
|
switch_state = 1;
|
|
tls_ecc_heap_free(tls_heap);
|
|
} else {
|
|
|
|
#ifdef ECC
|
|
tls_suite->retry_counter = 0;
|
|
switch_state = 1;
|
|
#else
|
|
tr_debug("NO ECC Sup");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_INTERNAL);
|
|
return buffer_free(buf);
|
|
#endif
|
|
|
|
}
|
|
if (switch_state) {
|
|
tls_suite->setups &= ~TLS_HANSHAKE_HASH;
|
|
sec_set_auth_timeout(tls_suite, TLS_HELLO_RX);
|
|
tls_suite->retry_counter = 0;
|
|
tls_handshake_copy(tls_msg_ptr, tls_heap);
|
|
}
|
|
} else {
|
|
tr_debug("TLS:S_Hello Fail: %02x", tls_suite->state);
|
|
}
|
|
} else {
|
|
tr_debug("SERver RE Tx drop Ser Hello");
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TLS_SERVER_HELLO_DONE:
|
|
if (tls_msg_ptr->len == 0) {
|
|
if (tls_suite->state >= TLS_CERTIFICATE_RX && tls_suite->state < PANA_ERROR) {
|
|
tr_debug("TLS:S_Hello DONE");
|
|
algo_ok |= 2;
|
|
tls_handshake_copy(tls_msg_ptr, tls_heap);
|
|
sec_lib_state_machine_trig(tls_suite, TLS_HELLO_DONE);
|
|
} else {
|
|
tr_debug("Drop Ser Hello Done: %02x", tls_suite->state);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TLS_CERTIFICATE:
|
|
#ifdef ECC
|
|
if (tls_suite->state == TLS_HELLO_RX) {
|
|
tr_debug("TLS Certi RX");
|
|
|
|
if (tls_parse_certificate(tls_msg_ptr->msg_ptr, tls_msg_ptr->len, tls_suite)) {
|
|
|
|
tls_suite->setups |= TLS_ECC_CERTIFICATE_RECEIVED;
|
|
algo_ok = 0;
|
|
tls_handshake_copy(tls_msg_ptr, tls_heap);
|
|
tls_suite->timer = pana_retry_req_max_get();
|
|
|
|
tls_suite->state = TLS_CERTIFICATE_RX;
|
|
certi_rx |= 1;
|
|
|
|
} else {
|
|
tr_debug("TLS Malformed Certificate");
|
|
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_BAD_CERTIFICATE);
|
|
return buffer_free(buf);
|
|
}
|
|
|
|
} else {
|
|
tr_debug("Drop Cert: %02x", tls_suite->state);
|
|
return buffer_free(buf);
|
|
}
|
|
#else
|
|
sec_lib_state_machine_trig(tls_suite, PANA_ERROR);
|
|
#endif
|
|
break;
|
|
|
|
case TLS_SERVER_KEY_EXCHANGE:
|
|
tr_debug(" TLS Serv KEY Exchange RX");
|
|
#ifdef ECC
|
|
if (!tls_parse_server_key_exchange(tls_msg_ptr->msg_ptr, tls_msg_ptr->len, tls_suite)) {
|
|
tr_debug("Drop Key");
|
|
sec_lib_state_machine_trig(tls_suite, PANA_ERROR);
|
|
} else {
|
|
algo_ok = 0;
|
|
tls_handshake_copy(tls_msg_ptr, tls_heap);
|
|
certi_rx |= 2;
|
|
sec_set_auth_timeout(tls_suite, TLS_SERVER_KEY_EXCHANGE_RX);
|
|
}
|
|
#else
|
|
tr_debug("Drop Key");
|
|
sec_lib_state_machine_trig(tls_suite, PANA_ERROR);
|
|
#endif
|
|
|
|
break;
|
|
|
|
case TLS_CERTIFICATE_REQUEST:
|
|
#ifdef ECC
|
|
if (tls_parse_certificate_request(tls_msg_ptr->msg_ptr, tls_msg_ptr->len)) {
|
|
tr_debug(" TLS Cert request- ");
|
|
if ((tls_suite->setups & TLS_ECC_CERTIFICATE_REQUESTED) == 0) {
|
|
tls_suite->setups |= TLS_ECC_CERTIFICATE_REQUESTED;
|
|
tls_handshake_copy(tls_msg_ptr, tls_heap);
|
|
|
|
}
|
|
} else
|
|
#endif
|
|
{
|
|
tr_debug("Client drop Cert Request");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_DECRYPT);
|
|
return buffer_free(buf);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
ptr = tls_msg_ptr->msg_ptr;
|
|
ptr += tls_msg_ptr->len;
|
|
j++;
|
|
}
|
|
}
|
|
|
|
} else if (tls_header_ptr->type == TLS_CHANGE_CIPHER_SPEC && (tls_heap != 0) /*&& (tls_header[i].length == 1)*/) {
|
|
uint8_t tx_alert = 1;
|
|
tr_debug("TLS:Change ChipherS");
|
|
tr_debug("%02x", tls_suite->state);
|
|
if (tls_suite->state == TLS_KEY_CHANGE) {
|
|
tx_alert = 0;
|
|
}
|
|
|
|
if (tx_alert) {
|
|
tr_debug("Wrong state TX Alert");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_CLOSE_FATAL);
|
|
return buffer_free(buf);
|
|
} else {
|
|
sec_set_auth_timeout(tls_suite, TLS_CHANGE_CHIPHER);
|
|
algo_ok |= 8;
|
|
}
|
|
|
|
} else if (tls_header_ptr->type == TLS_ALERT_TYPE) {
|
|
tr_debug("Alert!!");
|
|
if (tls_header_ptr->length == 2) {
|
|
uint8_t *dptr = tls_header_ptr->ptr;
|
|
tr_debug("%s", tr_array(tls_header_ptr->ptr, 2));
|
|
//Skip Alert Type and descriptions
|
|
dptr += 2;
|
|
algo_ok = 0xf0;
|
|
sec_lib_state_machine_trig(tls_suite, PANA_FAILURE);
|
|
}
|
|
i = 0xfe;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (algo_ok) {
|
|
if (tls_suite->state == TLS_HELLO_RX) {
|
|
sec_set_auth_timeout(tls_suite, TLS_HELLO_RX);
|
|
tls_suite->retry_counter = 0;
|
|
i = 0xff;
|
|
} else if (tls_suite->state == TLS_HELLO_DONE) {
|
|
//ADD already Now Client key change handshake part
|
|
#ifdef ECC
|
|
if (tls_heap->tls_chipher_mode == CHIPHER_ECC) {
|
|
if (tls_suite->setups & TLS_ECC_CERTIFICATE_REQUESTED) {
|
|
tr_debug("Message verify start");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ECC_MESSAGE_VERIFY_START);
|
|
} else {
|
|
tr_debug("Cert REQ diabled");
|
|
}
|
|
} else
|
|
#endif
|
|
{
|
|
|
|
tls_msg_t *tmp_msg = tls_msg_ptr_get();
|
|
|
|
tmp_msg->len = 3;
|
|
if (tls_suite->psk_key_id > 0xff) {
|
|
tmp_msg->len++;
|
|
}
|
|
ptr = buf->buf;
|
|
*ptr++ = TLS_CLIENT_KEY_EXCHANGE;
|
|
ptr = common_write_24_bit(tmp_msg->len, ptr);
|
|
tmp_msg->msg_ptr = ptr;
|
|
ptr = common_write_16_bit(tmp_msg->len - 2, ptr);
|
|
if (tls_suite->psk_key_id > 0xff) {
|
|
*ptr++ = tls_suite->psk_key_id >> 8;
|
|
}
|
|
|
|
*ptr = tls_suite->psk_key_id;;
|
|
tls_handshake_copy(tmp_msg, tls_heap);
|
|
sec_prf_state_set(tls_suite);
|
|
}
|
|
i = 0xff;
|
|
} else if (tls_suite->state == TLS_CHANGE_CHIPHER) {
|
|
tr_debug("No Chipher Set Close state");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_INTERNAL);
|
|
i = 0xff;
|
|
} else if (tls_suite->state == TLS_FINISH) {
|
|
tr_debug("Finish RX");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_FINISH);
|
|
i = 0xff;
|
|
} else if (algo_ok == 0x18) {
|
|
|
|
} else {
|
|
i = 11;
|
|
tr_debug("%02x", algo_ok);
|
|
}
|
|
}
|
|
|
|
if (i) {
|
|
buf = tls_certificate_buffer_store(buf, certi_rx, tls_suite);
|
|
}
|
|
return (buf);
|
|
}
|
|
|
|
|
|
|
|
buffer_t *tls_server_up(buffer_t *buf, sec_suite_t *tls_suite)
|
|
{
|
|
#ifdef PANA_SERVER_API
|
|
uint8_t i = 0, certi_rx = 0;
|
|
uint16_t data_len = 0;
|
|
uint8_t alert_case = 0;
|
|
uint8_t *ptr;
|
|
tls_header_t *tls_header_ptr;
|
|
tls_heap_t *tls_heap = tls_suite->tls_session->tls_heap;
|
|
uint8_t algo_ok = 0, j = 0;
|
|
ptr = buffer_data_pointer(buf);
|
|
|
|
i = 1;
|
|
while (buf->buf_ptr < buf->buf_end) {
|
|
data_len = buffer_data_length(buf);
|
|
ptr = buffer_data_pointer(buf);
|
|
tls_header_ptr = NULL;
|
|
|
|
if (data_len >= 5) {
|
|
uint16_t tls_version;
|
|
tls_header.type = *ptr++;
|
|
tls_version = common_read_16_bit(ptr);
|
|
ptr += 2;
|
|
if (tls_version != TLS_1_2_VERSION) {
|
|
tr_debug("Len: %04x", data_len);
|
|
tr_debug("%s", tr_array(ptr, 4));
|
|
alert_case = 4;
|
|
} else {
|
|
tls_header.length = common_read_16_bit(ptr);
|
|
ptr += 2;
|
|
data_len -= 5;
|
|
if (tls_header.length > data_len) {
|
|
alert_case = 5;
|
|
} else {
|
|
tr_debug("Full TLS Record");
|
|
tls_header.ptr = ptr;
|
|
buf->buf_ptr += tls_header.length;
|
|
buf->buf_ptr += 5;
|
|
tls_header_ptr = &tls_header;
|
|
}
|
|
}
|
|
} else {
|
|
alert_case = 5;
|
|
}
|
|
|
|
if (alert_case) {
|
|
tr_debug("TLS Segmentation or datagram error: %02x", alert_case);
|
|
buf->buf_ptr = buf->buf_end;
|
|
//SET Alert Case
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_INTERNAL);
|
|
return buffer_free(buf);
|
|
}
|
|
|
|
if (tls_header_ptr) {
|
|
if (tls_header_ptr->type == TLS_HANDSHAKE && (tls_heap != 0)) {
|
|
tr_debug("Type:Handshake");
|
|
if (tls_suite->state == TLS_CHANGE_CHIPHER) {
|
|
if (tls_header_ptr->length < 32) {
|
|
tr_debug("Too short Chiher Text");
|
|
} else if ((algo_ok & 0x20) && (tls_suite->state == PRF_CALC)) {
|
|
tr_debug("Drop Client RE TX");
|
|
/*tls_text_cnt = */j = 1;
|
|
} else {
|
|
buf = tls_verify_handler(certi_rx, tls_header_ptr, buf, tls_suite);
|
|
if (!buf) {
|
|
return buf;
|
|
}
|
|
}
|
|
} else {
|
|
uint8_t tls_msg_cnt = 0;
|
|
tls_msg_t *tls_msg_ptr = 0;
|
|
if (algo_ok != 0x18) {
|
|
tls_msg_cnt = tls_msg_analyzy(tls_header_ptr->ptr, tls_header_ptr->length);
|
|
j = 0;
|
|
}
|
|
ptr = tls_header_ptr->ptr;
|
|
while (j < tls_msg_cnt) {
|
|
tls_msg_ptr = tls_msg_get(ptr);
|
|
|
|
switch (tls_msg_ptr->type) {
|
|
case TLS_CLIENT_HELLO:
|
|
//Parse
|
|
if (tls_parse_client_hello(tls_msg_ptr->msg_ptr, tls_msg_ptr->len, tls_suite)) {
|
|
tr_debug("TLS:C_Hello OK");
|
|
algo_ok = 0;
|
|
tls_heap->tls_handshake_h_len = 0;
|
|
tls_handshake_copy(tls_msg_ptr, tls_heap);
|
|
if (tls_heap->tls_chipher_mode == CHIPHER_ECC) {
|
|
#ifdef ECC
|
|
sec_lib_state_machine_trig(tls_suite, TLS_SERVER_ECC_PUB_KEY_GEN);
|
|
#else
|
|
tr_debug("NO ECC Sup");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_INTERNAL);
|
|
return buffer_free(buf);
|
|
#endif
|
|
|
|
} else {
|
|
tls_ecc_heap_free(tls_heap);
|
|
sec_lib_state_machine_trig(tls_suite, TLS_SERVER_TX_SERVER_HELLO);
|
|
}
|
|
|
|
} else {
|
|
tr_debug("TLS:C_Hello Fail");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_INTERNAL);
|
|
return buffer_free(buf);
|
|
}
|
|
break;
|
|
|
|
case TLS_CERTIFICATE:
|
|
#ifdef ECC
|
|
|
|
if (tls_suite->state == TLS_TX_SERVER_KEY_EXCHANGE || tls_suite->state == TLS_SERVER_WAIT_CHANGE_CHIPHERSUITE) {
|
|
tr_debug("TLS Certi RX");
|
|
|
|
if (tls_parse_certificate(tls_msg_ptr->msg_ptr, tls_msg_ptr->len, tls_suite)) {
|
|
|
|
tls_suite->setups |= TLS_ECC_CERTIFICATE_RECEIVED;
|
|
algo_ok = 0;
|
|
tls_handshake_copy(tls_msg_ptr, tls_heap);
|
|
tls_suite->timer = pana_retry_req_max_get();
|
|
tls_suite->state = TLS_CERTIFICATE_RX;
|
|
certi_rx |= 1;
|
|
|
|
} else {
|
|
tr_debug("TLS Malformed Certificate");
|
|
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_BAD_CERTIFICATE);
|
|
return buffer_free(buf);
|
|
}
|
|
|
|
} else {
|
|
tr_debug("Drop Cert: %02x", tls_suite->state);
|
|
return buffer_free(buf);
|
|
}
|
|
#else
|
|
sec_lib_state_machine_trig(tls_suite, PANA_ERROR);
|
|
#endif
|
|
break;
|
|
|
|
case TLS_CLIENT_KEY_EXCHANGE:
|
|
tr_debug(" TLS Client KEY Exchange RX");
|
|
if (tls_heap->tls_chipher_mode == CHIPHER_PSK) {
|
|
uint8_t *d_ptr = tls_msg_ptr->msg_ptr;
|
|
uint16_t key_len;
|
|
uint16_t received_key_id = 0;
|
|
|
|
key_len = common_read_16_bit(d_ptr);
|
|
d_ptr += 2;
|
|
|
|
if (key_len) {
|
|
if (key_len == 2) {
|
|
received_key_id = (*d_ptr++) << 8;
|
|
}
|
|
received_key_id += *d_ptr;
|
|
}
|
|
|
|
if (tls_get_key(received_key_id) != NULL) {
|
|
tls_suite->psk_key_id = received_key_id;
|
|
|
|
if (tls_suite->state != PRF_CALC) {
|
|
tr_debug("Client KEY Exchange ");
|
|
tls_handshake_copy(tls_msg_ptr, tls_heap);
|
|
algo_ok = 0;
|
|
} else {
|
|
tr_debug("Client Re TX");
|
|
}
|
|
}
|
|
|
|
/* Not valid Key ID */
|
|
else {
|
|
tr_debug("Server drop Client Key Exchange");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_DECRYPT);
|
|
return buffer_free(buf);
|
|
}
|
|
} else {
|
|
#ifdef ECC
|
|
if (tls_parse_client_key_exchange(tls_msg_ptr->msg_ptr, tls_msg_ptr->len, tls_suite)) {
|
|
algo_ok = 0;
|
|
tls_handshake_copy(tls_msg_ptr, tls_heap);
|
|
sec_set_auth_timeout(tls_suite, TLS_CLIENT_KEY_EXCHANGE_RX);
|
|
} else
|
|
#endif
|
|
{
|
|
tr_debug("Server drop Client Key EX");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_DECRYPT);
|
|
return buffer_free(buf);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TLS_CERTIFICATE_VERIFY:
|
|
tr_debug(" TLS Cert Verify ");
|
|
#ifdef ECC
|
|
if (tls_parse_certificate_verify(tls_msg_ptr->msg_ptr, tls_msg_ptr->len, tls_suite)) {
|
|
|
|
if ((tls_suite->setups & TLS_ECC_CERTIFICATE_VERIFY) == 0) {
|
|
tr_debug("Calc Hash for Cert Verify");
|
|
tls_suite->setups |= TLS_ECC_CERTIFICATE_VERIFY;
|
|
tls_hanshake_hash_cal(tls_heap);
|
|
tls_handshake_copy(tls_msg_ptr, tls_heap);
|
|
certi_rx |= 2;
|
|
}
|
|
} else
|
|
#endif
|
|
{
|
|
tr_debug("Client Cert Verfify fail");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_DECRYPT);
|
|
return buffer_free(buf);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
ptr = tls_msg_ptr->msg_ptr;
|
|
ptr += tls_msg_ptr->len;
|
|
j++;
|
|
}
|
|
}
|
|
|
|
} else if (tls_header_ptr->type == TLS_CHANGE_CIPHER_SPEC && (tls_heap != 0) /*&& (tls_header[i].length == 1)*/) {
|
|
uint8_t tx_alert = 1;
|
|
tr_debug("TLS:Change ChipherS");
|
|
tr_debug("%02x", tls_suite->state);
|
|
if (tls_suite->state == TLS_CLIENT_KEY_EXCHANGE_RX || tls_suite->state == TLS_SERVER_WAIT_CHANGE_CHIPHERSUITE) {
|
|
tx_alert = 0;
|
|
}
|
|
|
|
if (tx_alert) {
|
|
tr_debug("Wrong state TX Alert");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_CLOSE_FATAL);
|
|
return buffer_free(buf);
|
|
} else {
|
|
sec_set_auth_timeout(tls_suite, TLS_CHANGE_CHIPHER);
|
|
algo_ok |= 8;
|
|
}
|
|
|
|
} else if (tls_header_ptr->type == TLS_ALERT_TYPE) {
|
|
tr_debug("Alert!!");
|
|
if (tls_header_ptr->length == 2) {
|
|
uint8_t *dptr = tls_header_ptr->ptr;
|
|
tr_debug("%s", tr_array(tls_header_ptr->ptr, 2));
|
|
//Skip Alert Type and descriptions
|
|
dptr += 2;
|
|
algo_ok = 0xf0;
|
|
sec_lib_state_machine_trig(tls_suite, PANA_FAILURE);
|
|
}
|
|
i = 0xfe;
|
|
}
|
|
}
|
|
}
|
|
if (algo_ok) {
|
|
if (tls_suite->state == TLS_CHANGE_CHIPHER) {
|
|
tr_debug("No Chipher RX--TXalert");
|
|
sec_lib_state_machine_trig(tls_suite, TLS_ALERT_INTERNAL);
|
|
i = 0xff;
|
|
} else if (algo_ok == 0x18) {
|
|
|
|
} else {
|
|
i = 11;
|
|
tr_debug("%02x", algo_ok);
|
|
}
|
|
}
|
|
|
|
if (i) {
|
|
buf = tls_certificate_buffer_store(buf, certi_rx, tls_suite);
|
|
}
|
|
#else
|
|
(void)tls_suite;
|
|
if (buf) {
|
|
buf = buffer_free(buf);
|
|
}
|
|
#endif
|
|
return (buf);
|
|
}
|
|
|
|
|
|
buffer_t *tls_client_hello_build(buffer_t *buf, sec_suite_t *tls_suite)
|
|
{
|
|
uint8_t *ptr;
|
|
tls_msg_t *tmp_msg = tls_msg_ptr_get();
|
|
tls_heap_t *tls_heap = tls_suite->tls_session->tls_heap;
|
|
tr_debug("TTLs TX:Client Hello");
|
|
//Build Client Hello
|
|
ptr = buffer_data_clear(buf);
|
|
//for Hash calculation
|
|
|
|
*ptr++ = TLS_CLIENT_HELLO;
|
|
ptr += 3; // skip length, fill in at the end
|
|
tmp_msg->msg_ptr = ptr;
|
|
ptr = common_write_16_bit(TLS_1_2_VERSION, ptr);
|
|
memcpy(ptr, (tls_heap->tls_hello_random + CLIENT_HELLO_PTR), 32);
|
|
ptr += 32;
|
|
*ptr++ = 0; //Session ID length
|
|
ptr += 2; // Skip cipher suite length; fill in a moment
|
|
uint8_t *ciphers_ptr = ptr;
|
|
#ifdef ECC
|
|
if (tls_suite->supported_chipher_suites & SEC_CIPHERSUITE_ECC) {
|
|
ptr = common_write_16_bit(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, ptr);
|
|
ptr = common_write_16_bit(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8_COMPAT, ptr);
|
|
}
|
|
#endif
|
|
if (tls_suite->supported_chipher_suites & SEC_CIPHERSUITE_PSK) {
|
|
ptr = common_write_16_bit(TLS_PSK_WITH_AES_128_CCM_8, ptr);
|
|
}
|
|
// Go back and fill in length
|
|
common_write_16_bit(ptr - ciphers_ptr, ciphers_ptr - 2);
|
|
|
|
*ptr++ = 1; // 1 Compression method
|
|
*ptr++ = TLS_COMPRESSION_METHOD_NULL;
|
|
#ifdef ECC
|
|
|
|
//Set ECC Extensions
|
|
if (tls_suite->supported_chipher_suites & SEC_CIPHERSUITE_ECC) {
|
|
ptr = common_write_16_bit(8 + 8 + 6, ptr); //Extensions length
|
|
|
|
ptr = common_write_16_bit(TLS_EXTENSION_SIGNATURE_ALGORITHMS, ptr);
|
|
ptr = common_write_16_bit(4, ptr); //extension data len
|
|
ptr = common_write_16_bit(2, ptr); //algorithm list len
|
|
ptr = common_write_16_bit(TLS_SIG_HASH_ALG_SHA256_ECDSA, ptr);
|
|
|
|
ptr = common_write_16_bit(TLS_EXTENSION_ELLIPTIC_CURVES, ptr);
|
|
ptr = common_write_16_bit(4, ptr); //extension data len
|
|
ptr = common_write_16_bit(2, ptr); //curve list len
|
|
ptr = common_write_16_bit(TLS_NAMED_CURVE_SECP256R1, ptr);
|
|
|
|
ptr = common_write_16_bit(TLS_EXTENSION_EC_POINT_FORMATS, ptr);
|
|
ptr = common_write_16_bit(2, ptr); //extension data len
|
|
*ptr++ = 1; // format list len
|
|
*ptr++ = 0; //Uncompressed mode
|
|
}
|
|
#endif
|
|
buffer_data_end_set(buf, ptr);
|
|
|
|
// Go back and write the length
|
|
uint16_t tls_len = buffer_data_length(buf) - 4;
|
|
tmp_msg->len = tls_len;
|
|
common_write_24_bit(tls_len, buffer_data_pointer(buf) + 1);
|
|
|
|
tls_heap->tls_handshake_h_len = 0;
|
|
tls_handshake_copy(tmp_msg, tls_heap);
|
|
tls_suite->setups |= TLS_HANSHAKE_HASH;
|
|
return tls_down(buf);
|
|
|
|
}
|
|
|
|
#ifdef ECC
|
|
uint8_t *tls_server_key_excahnge_msg_build(uint8_t *ptr, tls_heap_t *heap_ptr)
|
|
{
|
|
uint8_t r_zeros;
|
|
uint8_t s_zeros;
|
|
|
|
r_zeros = tls_get_leading_zeros(heap_ptr->ecc_heap->sgnt->m_R.data);
|
|
s_zeros = tls_get_leading_zeros(heap_ptr->ecc_heap->sgnt->m_s.data);
|
|
*ptr++ = TLS_SERVER_KEY_EXCHANGE;
|
|
ptr = common_write_24_bit((145 - r_zeros - s_zeros), ptr);
|
|
*ptr++ = 3; //type
|
|
ptr = common_write_16_bit(TLS_NAMED_CURVE_SECP256R1, ptr);
|
|
//There shuold be calculated case now only test purpose
|
|
*ptr++ = 65; //len
|
|
*ptr++ = 4; //type
|
|
memcpy(ptr, heap_ptr->ecc_heap->server_public_key, 64);
|
|
ptr += 64;
|
|
ptr = common_write_16_bit(TLS_SIG_HASH_ALG_SHA256_ECDSA, ptr);
|
|
ptr = common_write_16_bit((72 - r_zeros - s_zeros), ptr);
|
|
*ptr++ = 0x30;
|
|
*ptr++ = 70 - r_zeros - s_zeros;
|
|
ptr += tls_write_signature_parameters(ptr, ((uint8_t *)heap_ptr->ecc_heap->sgnt->m_R.data), r_zeros);
|
|
ptr += tls_write_signature_parameters(ptr, ((uint8_t *)heap_ptr->ecc_heap->sgnt->m_s.data), s_zeros);
|
|
return ptr;
|
|
}
|
|
|
|
|
|
uint8_t *tls_certificate_verify_msg_set(uint8_t *ptr, tls_heap_t *heap_ptr)
|
|
{
|
|
uint8_t r_zeros;
|
|
uint8_t s_zeros;
|
|
r_zeros = tls_get_leading_zeros(heap_ptr->ecc_heap->sgnt->m_R.data);
|
|
s_zeros = tls_get_leading_zeros(heap_ptr->ecc_heap->sgnt->m_s.data);
|
|
|
|
*ptr++ = TLS_CERTIFICATE_VERIFY;
|
|
ptr = common_write_24_bit((76 - r_zeros - s_zeros), ptr);
|
|
*ptr++ = 4;
|
|
*ptr++ = 3;
|
|
*ptr++ = 0;
|
|
*ptr++ = 72 - r_zeros - s_zeros;
|
|
*ptr++ = 0x30;
|
|
*ptr++ = 70 - r_zeros - s_zeros;
|
|
ptr += tls_write_signature_parameters(ptr, ((uint8_t *)heap_ptr->ecc_heap->sgnt->m_R.data), r_zeros);
|
|
ptr += tls_write_signature_parameters(ptr, ((uint8_t *)heap_ptr->ecc_heap->sgnt->m_s.data), s_zeros);
|
|
return ptr;
|
|
}
|
|
#define CERTI_CHAIN_3
|
|
|
|
uint16_t tls_certificate_len(certificate_chain_internal_t *temp)
|
|
{
|
|
uint8_t i;
|
|
uint16_t len = 0;
|
|
|
|
if (temp) {
|
|
len += 10;
|
|
if (temp->chain_length > 1) {
|
|
for (i = 0; i < (temp->chain_length - 1); i++) {
|
|
if (i) {
|
|
len += 3;
|
|
}
|
|
len += temp->certi_len[i + 1];
|
|
}
|
|
} else if (temp->chain_length == 1) {
|
|
len += temp->certi_len[0];
|
|
}
|
|
}
|
|
return len;
|
|
}
|
|
|
|
uint8_t *tls_certificate_msg_set(uint8_t *ptr, certificate_chain_internal_t *temp)
|
|
{
|
|
uint8_t i;
|
|
uint16_t len = 0;
|
|
len = tls_certificate_len(temp);
|
|
if (temp) {
|
|
len -= 4; // Cut TLS haeder space off
|
|
/* Set Certificate */
|
|
*ptr++ = TLS_CERTIFICATE;
|
|
ptr = common_write_24_bit(len, ptr);
|
|
len -= 3;
|
|
ptr = common_write_24_bit(len, ptr);
|
|
|
|
i = temp->chain_length;
|
|
if (i > 1) {
|
|
while (i) {
|
|
i--;
|
|
if (i) {
|
|
ptr = common_write_24_bit(temp->certi_len[i], ptr);
|
|
memcpy(ptr, temp->certi_chain[i], temp->certi_len[i]);
|
|
ptr += temp->certi_len[i];
|
|
}
|
|
}
|
|
} else if (i == 1) {
|
|
ptr = common_write_24_bit(temp->certi_len[0], ptr);
|
|
memcpy(ptr, temp->certi_chain[0], temp->certi_len[0]);
|
|
ptr += temp->certi_len[0];
|
|
}
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
uint8_t tls_write_signature_parameters(uint8_t *ptr, uint8_t *signature_parameter, uint8_t leadin_zeros)
|
|
{
|
|
uint8_t len = 2;
|
|
uint8_t i;
|
|
*ptr++ = 2;
|
|
*ptr++ = 33 - leadin_zeros;
|
|
if (leadin_zeros == 0) {
|
|
*ptr++ = 0;
|
|
len += 33;
|
|
} else {
|
|
leadin_zeros -= 1;
|
|
len += (32 - leadin_zeros);
|
|
}
|
|
for (i = leadin_zeros; i < 32; i++) {
|
|
*ptr++ = signature_parameter[31 - i];
|
|
}
|
|
return len;
|
|
}
|
|
|
|
void tls_ecc_point_reverse_order(uint8_t *dst, uint8_t *src)
|
|
{
|
|
uint8_t i;
|
|
for (i = 0; i < 32; i++) {
|
|
dst[i] = src[31 - i];
|
|
}
|
|
}
|
|
#endif
|
|
|
|
uint8_t *tls_build_server_hello_msg(uint8_t *ptr, tls_session_t *tls_session)
|
|
{
|
|
tls_heap_t *heap_ptr = tls_session->tls_heap;
|
|
*ptr++ = TLS_SERVER_HELLO;
|
|
ptr += 3; // fill length in at the end
|
|
uint8_t *startptr = ptr;
|
|
ptr = common_write_16_bit(TLS_1_2_VERSION, ptr);
|
|
|
|
memcpy(ptr, (heap_ptr->tls_hello_random + SERVER_HELLO_PTR), 32);
|
|
ptr += 32;
|
|
|
|
*ptr++ = tls_session->id_length;
|
|
memcpy(ptr, tls_session->tls_session_id, tls_session->id_length);
|
|
ptr += tls_session->id_length;
|
|
|
|
uint16_t ciphersuite;
|
|
#ifdef ECC
|
|
if (heap_ptr->tls_chipher_mode == CHIPHER_ECC) {
|
|
ciphersuite = heap_ptr->client_knows_standard_ecc_ciphersuite ?
|
|
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 :
|
|
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8_COMPAT;
|
|
} else
|
|
#endif
|
|
{
|
|
ciphersuite = TLS_PSK_WITH_AES_128_CCM_8;
|
|
}
|
|
|
|
ptr = common_write_16_bit(ciphersuite, ptr);
|
|
*ptr++ = TLS_COMPRESSION_METHOD_NULL;
|
|
|
|
if (heap_ptr->tls_chipher_mode == CHIPHER_ECC) {
|
|
ptr = common_write_16_bit(6, ptr); // 6 bytes of Extensions
|
|
ptr = common_write_16_bit(TLS_EXTENSION_EC_POINT_FORMATS, ptr);
|
|
ptr = common_write_16_bit(2, ptr); // 2 bytes of extension data
|
|
*ptr++ = 1; // 1 byte of ec_point_format_list
|
|
*ptr++ = 0; // ECPointFormat::uncompressed
|
|
}
|
|
|
|
// Go back and fill in length
|
|
common_write_24_bit(ptr - startptr, startptr - 3);
|
|
|
|
if (heap_ptr->tls_chipher_mode != CHIPHER_ECC) {
|
|
*ptr++ = TLS_SERVER_HELLO_DONE;
|
|
ptr = common_write_24_bit(0, ptr); // length
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
void tls_header_set(buffer_t *buf)
|
|
{
|
|
uint8_t *ptr;
|
|
uint16_t len;
|
|
ptr = buffer_data_pointer(buf);
|
|
len = buffer_data_length(buf);
|
|
len -= 5; //Cut Flags byte off
|
|
*ptr++ = TLS_HANDSHAKE;
|
|
ptr = common_write_16_bit(TLS_1_2_VERSION, ptr);
|
|
ptr = common_write_16_bit(len, ptr);
|
|
}
|
|
|
|
void tls_session_id_genrate(uint8_t *suite, uint8_t length)
|
|
{
|
|
if (length > 32) {
|
|
length = 32;
|
|
}
|
|
randLIB_get_n_bytes_random(suite, length);
|
|
}
|
|
|
|
tls_heap_t *tls_heap_allocate(void)
|
|
{
|
|
tls_heap_t *heap_ptr = tls_heap_structure_allocate();
|
|
if (heap_ptr) {
|
|
#ifdef ECC
|
|
tls_ecc_heap_t *ecc_ptr = ecc_allocate_ram();
|
|
if (ecc_ptr == 0) {
|
|
tr_debug("ECC Alloc Fail");
|
|
ns_dyn_mem_free(heap_ptr);
|
|
heap_ptr = 0;
|
|
return heap_ptr;
|
|
} else {
|
|
//uint8_t *ptr, i;
|
|
heap_ptr->ecc_heap = ecc_ptr;
|
|
}
|
|
heap_ptr->client_knows_standard_ecc_ciphersuite = false;
|
|
#endif
|
|
randLIB_get_n_bytes_random(heap_ptr->tls_hello_random, 64);
|
|
ns_sha256_init(&heap_ptr->sha256_ctx);
|
|
heap_ptr->tls_chipher_mode = CHIPHER_NONE;
|
|
heap_ptr->tls_handshake_h_len = 0;
|
|
heap_ptr->client_verify_buf = 0;
|
|
heap_ptr->client_verify_buf_len = 0;
|
|
}
|
|
return heap_ptr;
|
|
}
|
|
|
|
void tls_heap_free(tls_heap_t *heap_ptr)
|
|
{
|
|
if (heap_ptr) {
|
|
if (heap_ptr->cert_temp_buf) {
|
|
if (heap_ptr->signature_temp_buf) {
|
|
if (heap_ptr->signature_temp_buf == heap_ptr->cert_temp_buf) {
|
|
heap_ptr->signature_temp_buf = 0;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
if (heap_ptr->pointer_types & 1) {
|
|
buffer_free(heap_ptr->cert_temp_buf);
|
|
} else {
|
|
ns_dyn_mem_free(heap_ptr->cert_temp_buf);
|
|
}
|
|
heap_ptr->cert_temp_buf = 0;
|
|
}
|
|
if (heap_ptr->signature_temp_buf) {
|
|
if (heap_ptr->pointer_types & 2) {
|
|
buffer_free(heap_ptr->signature_temp_buf);
|
|
} else {
|
|
ns_dyn_mem_free(heap_ptr->signature_temp_buf);
|
|
}
|
|
heap_ptr->signature_temp_buf = 0;
|
|
}
|
|
if (heap_ptr->client_verify_buf) {
|
|
ns_dyn_mem_free(heap_ptr->client_verify_buf);
|
|
heap_ptr->client_verify_buf = 0;
|
|
}
|
|
tls_ecc_heap_free(heap_ptr);
|
|
ns_sha256_free(&heap_ptr->sha256_ctx);
|
|
ns_dyn_mem_free(heap_ptr);
|
|
}
|
|
}
|
|
#ifdef ECC
|
|
void tls_ecc_heap_free(tls_heap_t *heap_ptr)
|
|
{
|
|
if (heap_ptr) {
|
|
if (heap_ptr->ecc_heap) {
|
|
if (heap_ptr->ecc_heap->sgnt) {
|
|
ecc_library_free_pointer(heap_ptr->ecc_heap->sgnt);
|
|
//ns_dyn_mem_free(heap_ptr->ecc_heap->sgnt);
|
|
}
|
|
ns_dyn_mem_free(heap_ptr->ecc_heap);
|
|
heap_ptr->ecc_heap = 0;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef ECC
|
|
uint8_t tls_get_leading_zeros(void *data)
|
|
{
|
|
|
|
uint8_t *ptr = (uint8_t *)data + 31;
|
|
uint8_t i = 0;
|
|
|
|
for (;; ptr--) {
|
|
if (*ptr & 0x80) {
|
|
break;
|
|
}
|
|
i++;
|
|
if (i == 33) {
|
|
break;
|
|
}
|
|
|
|
if (*ptr) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
void tls_key_expansion_cal(tls_heap_t *heap_ptr, uint8_t *key_save_ptr, uint8_t *master_secret)
|
|
{
|
|
uint8_t *ptr;
|
|
prf_sec_param_t *prf_ptr = shalib_prf_param_get();
|
|
prf_ptr->secret = master_secret;
|
|
prf_ptr->sec_len = 48;
|
|
prf_ptr->label = "key expansion";
|
|
prf_ptr->seed = heap_ptr->temp_buf;
|
|
ptr = heap_ptr->temp_buf;
|
|
memcpy(ptr, (heap_ptr->tls_hello_random + SERVER_HELLO_PTR), 32);
|
|
ptr += 32;
|
|
memcpy(ptr, (heap_ptr->tls_hello_random + CLIENT_HELLO_PTR), 32);
|
|
prf_ptr->seedlen = 64;
|
|
shalib_prf_calc(key_save_ptr, 10); // Why 40 bytes?
|
|
}
|
|
|
|
void tls_master_key_cal(tls_heap_t *heap_ptr, sec_suite_t *tls_suite)
|
|
{
|
|
uint8_t *ptr;
|
|
prf_sec_param_t *prf_ptr = shalib_prf_param_get();
|
|
uint8_t secret_buf[2 + 16 + 2 + 16];
|
|
tr_debug("CAL Master secret:");
|
|
//Her have to to be set check is
|
|
#ifdef ECC
|
|
if (heap_ptr->tls_chipher_mode == CHIPHER_ECC) {
|
|
prf_ptr->secret = heap_ptr->ecc_heap->pre_secret_mat;
|
|
prf_ptr->sec_len = 32;
|
|
} else
|
|
#endif
|
|
{
|
|
tls_psk_key_t *key_temp = tls_get_key(tls_suite->psk_key_id);
|
|
if (key_temp) {
|
|
/* RFC 4279 - premaster secret for N-octet PSK is
|
|
* +----------+----------+----------+----------+
|
|
* | 2 octets | N octets | 2 octets | N octets |
|
|
* +----------+----------+----------+----------+
|
|
* | N | 0 | N | PSK |
|
|
* +----------+----------+----------+----------+
|
|
*/
|
|
ptr = secret_buf;
|
|
ptr = common_write_16_bit(16, ptr);
|
|
memset(ptr, 0, 16), ptr += 16;
|
|
ptr = common_write_16_bit(16, ptr);
|
|
memcpy(ptr, key_temp->psk_key, 16);
|
|
prf_ptr->secret = secret_buf;
|
|
prf_ptr->sec_len = sizeof secret_buf;
|
|
}
|
|
}
|
|
prf_ptr->label = "master secret";
|
|
prf_ptr->seed = heap_ptr->temp_buf;
|
|
ptr = heap_ptr->temp_buf;
|
|
memcpy(ptr, (heap_ptr->tls_hello_random + CLIENT_HELLO_PTR), 32);
|
|
ptr += 32;
|
|
memcpy(ptr, (heap_ptr->tls_hello_random + SERVER_HELLO_PTR), 32);
|
|
prf_ptr->seedlen = 64;
|
|
|
|
shalib_prf_calc(tls_suite->tls_session->master_secret, 12);
|
|
}
|
|
|
|
void tls_verify_calc(uint8_t output[12], uint8_t server, tls_heap_t *heap_ptr, uint8_t *master_secret)
|
|
{
|
|
prf_sec_param_t *prf_ptr = shalib_prf_param_get();
|
|
prf_ptr->secret = master_secret;
|
|
prf_ptr->sec_len = 48;
|
|
prf_ptr->label = server ? "server finished" : "client finished";
|
|
prf_ptr->seed = heap_ptr->hash_buf;
|
|
prf_ptr->seedlen = 32;
|
|
shalib_prf_calc(output, 3);
|
|
}
|
|
|
|
|
|
void tls_handshake_copy(tls_msg_t *tls_msg_ptr, tls_heap_t *heap_ptr)
|
|
{
|
|
uint16_t len = tls_msg_ptr->len;
|
|
uint8_t *ptr = tls_msg_ptr->msg_ptr;
|
|
ptr -= 4;
|
|
len += 4;
|
|
|
|
if (heap_ptr->tls_handshake_h_len == 0) {
|
|
ns_sha256_starts(&heap_ptr->sha256_ctx);
|
|
}
|
|
ns_sha256_update(&heap_ptr->sha256_ctx, ptr, len);
|
|
heap_ptr->tls_handshake_h_len += len;
|
|
}
|
|
|
|
|
|
void tls_hanshake_hash_cal(tls_heap_t *heap_ptr)
|
|
{
|
|
tr_debug("HASH Calc");
|
|
ns_sha256_context ctx;
|
|
ns_sha256_clone(&ctx, &heap_ptr->sha256_ctx);
|
|
ns_sha256_finish(&ctx, heap_ptr->hash_buf);
|
|
ns_sha256_free(&ctx);
|
|
}
|
|
|
|
#if 0
|
|
uint8_t tls_txt_analyze(buffer_t *buf)
|
|
{
|
|
uint8_t *dptr;
|
|
uint8_t tls_text_cnt = 0;
|
|
uint16_t data_len = buffer_data_length(buf);
|
|
uint16_t readed = 0;
|
|
dptr = buffer_data_pointer(buf);
|
|
|
|
while (readed < data_len) {
|
|
uint16_t tls_version;
|
|
tls_header.type = *dptr++;
|
|
tls_version = common_read_16_bit(dptr);
|
|
dptr += 2;
|
|
if (tls_version == TLS_1_2_VERSION) {
|
|
tls_text_cnt = 0;
|
|
break;
|
|
} else {
|
|
uint16_t tls_temp_var_16;
|
|
tls_temp_var_16 = common_read_16_bit(dptr);
|
|
dptr += 2;
|
|
if (tls_temp_var_16) {
|
|
tls_header.length = tls_temp_var_16;
|
|
tls_header.ptr = dptr;
|
|
|
|
readed += 5;
|
|
readed += tls_temp_var_16;
|
|
|
|
if (readed > data_len) {
|
|
tr_debug("Over Read1: %02x", tls_header.type);
|
|
tr_debug("LEN: %04x", data_len);
|
|
tr_debug("Read: %04x", readed);
|
|
tls_text_cnt = 0;
|
|
break;
|
|
} else {
|
|
dptr += tls_temp_var_16;
|
|
tls_text_cnt++;
|
|
}
|
|
} else {
|
|
tls_text_cnt = 0;
|
|
break;;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (readed != data_len) {
|
|
tr_debug("TSL txt Parse Fail");
|
|
tls_text_cnt = 0;
|
|
}
|
|
return tls_text_cnt;
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
tls_header_t *tls_message_get(uint8_t *dptr)
|
|
{
|
|
uint16_t tls_temp_var_16;
|
|
tls_header.type = *dptr;
|
|
dptr += 3;
|
|
tls_temp_var_16 = common_read_16_bit(dptr);
|
|
dptr += 2;
|
|
tls_header.length = tls_temp_var_16;
|
|
tls_header.ptr = dptr;
|
|
return &tls_header;
|
|
}
|
|
#endif
|
|
|
|
uint8_t tls_msg_analyzy(uint8_t *ptr, uint16_t data_len)
|
|
{
|
|
uint8_t *dptr;
|
|
uint8_t msg_cnt = 0;
|
|
uint16_t readed = 0, m_len = 0;
|
|
dptr = ptr;
|
|
while (readed < data_len) {
|
|
dptr += 1; //Skip Type
|
|
if (*dptr++) {
|
|
//Too long skip packet
|
|
tr_debug("Too long: %s", tr_array(ptr, data_len));
|
|
msg_cnt = 0;
|
|
break;
|
|
} else {
|
|
m_len = common_read_16_bit(dptr);
|
|
dptr += 2;
|
|
}
|
|
readed += 4;
|
|
readed += m_len;
|
|
dptr += m_len;
|
|
|
|
if (readed > data_len) {
|
|
tr_debug("Over Read1: %02x", tls_msg.type);
|
|
tr_debug("LEN: %04x", data_len);
|
|
tr_debug("Read: %04x", readed);
|
|
msg_cnt = 0;
|
|
break;
|
|
} else {
|
|
msg_cnt++;
|
|
}
|
|
}
|
|
if (readed != data_len) {
|
|
tr_debug("TLS MSG Parse Fail");
|
|
msg_cnt = 0;
|
|
}
|
|
return msg_cnt;
|
|
}
|
|
|
|
tls_msg_t *tls_msg_get(uint8_t *dptr)
|
|
{
|
|
tls_msg.type = *dptr;
|
|
dptr += 2;
|
|
tls_msg.len = common_read_16_bit(dptr);
|
|
dptr += 2;
|
|
tls_msg.msg_ptr = dptr;
|
|
return &tls_msg;
|
|
}
|
|
|
|
tls_msg_t *tls_msg_ptr_get(void)
|
|
{
|
|
return &tls_msg;
|
|
}
|
|
|
|
void tls_build_client_verify_payload(tls_heap_t *tls_heap)
|
|
{
|
|
uint8_t *ptr;
|
|
ptr = tls_heap->hash_buf;
|
|
ptr = common_write_32_bit(0x1400000c, ptr);
|
|
memcpy(ptr, tls_heap->verify, 12);
|
|
}
|
|
|
|
void tls_nonce_update(uint8_t *ptr)
|
|
{
|
|
uint8_t i = 8;
|
|
ptr += 7;
|
|
|
|
while (i--) {
|
|
if (*ptr == 0xff) {
|
|
*ptr = 0;
|
|
ptr--;
|
|
} else {
|
|
*ptr += 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#ifdef ECC
|
|
uint8_t tls_parse_certificate_request(uint8_t *ptr, uint16_t len)
|
|
{
|
|
(void)len;
|
|
uint16_t hash_alg;
|
|
uint16_t count;
|
|
uint8_t found = 0;
|
|
count = *ptr++;
|
|
|
|
if (!count) {
|
|
tr_debug("cert req 0 count 1");
|
|
return 0;
|
|
}
|
|
|
|
while (count--) {
|
|
|
|
if (*ptr++ == TLS_CERT_TYPE_ECDSA) {
|
|
|
|
found = TLS_CERT_TYPE_ECDSA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found) {
|
|
tr_debug("cert req no supported type");
|
|
return 0;
|
|
}
|
|
found = 0;
|
|
|
|
count = (uint16_t) * ptr++ << 8;
|
|
count |= *ptr++;
|
|
count >>= 1;
|
|
|
|
if (!count) {
|
|
tr_debug("cert req 0 count 2");
|
|
return 0;
|
|
}
|
|
|
|
|
|
while (count--) {
|
|
|
|
hash_alg = common_read_16_bit(ptr);
|
|
ptr += 2;
|
|
if (hash_alg == TLS_SIG_HASH_ALG_SHA256_ECDSA) {
|
|
found = 1;
|
|
}
|
|
|
|
}
|
|
|
|
if (!found) {
|
|
|
|
tr_debug("cert req no supported Algo");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
/* There is also names field but we do not have parser for it yet */
|
|
|
|
}
|
|
|
|
|
|
static uint8_t ecc_verify_calculate_hash(sec_suite_t *tls_suite)
|
|
{
|
|
tls_heap_t *theap = tls_suite->tls_session->tls_heap;
|
|
if (!(tls_suite->setups & TLS_ECC_CERTIFICATE_RECEIVED)) {
|
|
return 1;
|
|
} else {
|
|
tls_suite->setups &= ~TLS_ECC_CERTIFICATE_RECEIVED;
|
|
}
|
|
|
|
if (tls_suite->setups & TLS_SERVER_MODE) {
|
|
if (!(tls_suite->setups & TLS_ECC_CERTIFICATE_VERIFY)) {
|
|
return 2;
|
|
} else {
|
|
tls_suite->setups &= ~TLS_ECC_CERTIFICATE_VERIFY;
|
|
}
|
|
}
|
|
if (!theap->ecc_heap->sgnt) {
|
|
return 3;
|
|
}
|
|
|
|
tls_ecc_server_key_signature_hash(theap);
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
void tls_ecc_reverse_hash(uint8_t *ptr)
|
|
{
|
|
uint8_t start = 0;
|
|
uint8_t end = 31;
|
|
uint8_t chr;
|
|
while (start < end) {
|
|
chr = ptr[start];
|
|
ptr[start] = ptr[end];
|
|
ptr[end] = chr;
|
|
|
|
start++;
|
|
end--;
|
|
}
|
|
}
|
|
|
|
void tls_ecc_server_key_signature_hash(tls_heap_t *heap_ptr)
|
|
{
|
|
memset(heap_ptr->ecc_heap->sgnt->m_m.data, 0, MPINT_DATA_SIZE);
|
|
ns_sha256_context ctx;
|
|
ns_sha256_init(&ctx);
|
|
ns_sha256_starts(&ctx);
|
|
ns_sha256_update(&ctx, heap_ptr->tls_hello_random, 64);
|
|
//ServerECDHParams(ECParameters+ECPoint)
|
|
heap_ptr->hash_buf[0] = TLS_EC_CURVE_TYPE_NAMED_CURVE;
|
|
common_write_16_bit(TLS_NAMED_CURVE_SECP256R1, heap_ptr->hash_buf + 1);
|
|
heap_ptr->hash_buf[3] = 65; // ECPoint public - length indicator for following 512-bit public key?
|
|
heap_ptr->hash_buf[4] = 4;
|
|
ns_sha256_update(&ctx, heap_ptr->hash_buf, 5);
|
|
ns_sha256_update(&ctx, heap_ptr->ecc_heap->server_public_key, 64);
|
|
ns_sha256_finish(&ctx, heap_ptr->ecc_heap->sgnt->m_m.data);
|
|
ns_sha256_free(&ctx);
|
|
tls_ecc_reverse_hash((uint8_t *)heap_ptr->ecc_heap->sgnt->m_m.data);
|
|
}
|
|
|
|
#endif
|
|
|
|
#else
|
|
int8_t arm_tls_add_psk_key(const uint8_t *key_ptr, uint16_t key_id)
|
|
{
|
|
(void)key_ptr;
|
|
(void)key_id;
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
|
|
|