mbed-os/connectivity/nanostack/sal-stack-nanostack/source/Security/TLS/tls_lib.c

2451 lines
81 KiB
C

/*
* Copyright (c) 2013-2021, Pelion 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();
static 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